如何在c#中检查变位字符串

本文关键字:字符串 检查 | 更新日期: 2023-09-27 18:14:34

给定两个字符串A和B,检查它们是否是字谜

如果一个字符串可以通过重新排列另一个字符串的字母得到,则称两个字符串为字谜。

字谜的例子有

  • dog, god
  • abac, baac
  • 123, 312

abab, aabadab, baad不是字谜。

输入:

输入的第一行是测试用例T的数量。后面跟着T行,每行有两个空格分隔的字符串A和B;

对于每个测试用例,如果它们是字谜,则打印"YES",否则打印"NO"。(没有引号)

  1. 1 <= T <= 10
  2. A和B都只包含小写拉丁字母"A"到"z"和数字0 ~ 9
  3. 每个字符串A和B的长度不超过5*10^5 (500000)

Sample Input            Sample Output
------------------------------------
3                           YES
abcd bcda                   NO
bad daa                     YES
a1b2c3 abc123               NO

我们该怎么做呢?

bool anagramChecker(string first, string second)
{
    if(first.Length != second.Length)
        return false;
    if(first == second)
        return true;//or false: Don't know whether a string counts as an anagram of itself
    Dictionary<char, int> pool = new Dictionary<char, int>();
    foreach(char element in first.ToCharArray()) //fill the dictionary with that available chars and count them up
    {
        if(pool.ContainsKey(element))
            pool[element]++;
        else
            pool.Add(element, 1);
    }
    foreach(char element in second.ToCharArray()) //take them out again
    {
        if(!pool.ContainsKey(element)) //if a char isn't there at all; we're out
            return false;
        if(--pool[element] == 0) //if a count is less than zero after decrement; we're out
            pool.Remove(element);
    }
    return pool.Count == 0;
}

如何在c#中检查变位字符串

这是你的解决方案吗?

string a = "abcd";
string b = "bcda"; // bad daa a1b2c3 abc123
string aa = String.Concat(a.OrderBy(c => c));
string bb = String.Concat(b.OrderBy(c => c));
if (aa == bb)
{
     Console.WriteLine("YES");
}
else
{
     Console.WriteLine("NO");
}

还是短

if (String.Concat(a.OrderBy(c => c)).Equals(String.Concat(b.OrderBy(c => c))) ...

有快速的方法和简单的方法:

void Test()
{
    string a = "abccabccabccabccabccabccabccabccabccabccabccabccabccabccabccabcc";
    string b = "bcacbcacbcacbcacbcacbcacbcacbcacbcacbcacbcacbcacbcacbcacbcacbcac";
    IsAnagramSimple(a, b);
    IsAnagramFast(a, b);
}

private bool IsAnagramSimple(string a, string b)
{
    return a.OrderBy(c => c).SequenceEqual(b.OrderBy(c => c));
}
private bool IsAnagramFast(string a, string b)
{
    if (a.Length != b.Length)
    {
        return false;
    }
    var aFrequency = CalculateFrequency(a);
    var bFrequency = CalculateFrequency(b);
    foreach (var key in aFrequency.Keys)
    {
        if (!bFrequency.ContainsKey(key)) return false;
        if (aFrequency[key] != bFrequency[key]) return false;
    }
    return true;
}
private Dictionary<char, int> CalculateFrequency(string input)
{
    var frequency = new Dictionary<char, int>();
    foreach (var c in input)
    {
        if (!frequency.ContainsKey(c))
        {
            frequency.Add(c, 0);
        }
        ++frequency[c];
    }
    return frequency;
}
public bool IsAnagram(string s1,string s2)
{
  if (s1.Length != s2.Length)
     return false;
  var s1Array = s1.ToLower().ToCharArray();
  var s2Array = s2.ToLower().ToCharArray();
  Array.Sort(s1Array);
  Array.Sort(s2Array);
  s1 = new string(s1Array);
  s2 = new string(s2Array);
  return s1 == s2;
}

另一种方法是检查第一个字符中是否包含第二个字符。然后从第一个字符中删除该字符,直到没有其他字符。

    private bool IsAnagram(string a, string b)
    {
        if (a.Length != b.Length) return false;
        List<char> list1 = a.ToList();
        List<char> list2 = b.ToList();
        for (int i = 0; i < a.Length; i++)
        {
            // try to remove list 1 item from list 2
            // if didn't find any thing to remove. so they are not anagram
            if (!list2.Remove(list1[i])) return false;
        }
        return true; // loop finished successfully. they are anagram
    }

请注意,List<T>.Remove()方法返回一个bool值,该值指定该方法是否能够删除任何东西。

你可以在一行中完成所有这些,Linq.

List<char> list = "god".ToList();
bool isAnagram = "dog".All(ch => list.Remove(ch));

Linq方法All<char>(Func<char,bool>)将执行委托,直到Func<char,bool>返回false或直到查询结束。如果函数返回false,则All也返回false。否则返回true

下面是一个不对两个数组排序的算法。假设字典的ContainsKey, Add, Remove方法为O(1),则算法的时间复杂度为O(N),而不是使用Sort的O(nlogn)。

static bool anagram(string s1, string s2)
    {
        if (s1.Length != s2.Length)
        {
            return false;
        }
        Dictionary<char, int> bucket = new Dictionary<char, int>(50); 
        for (int i = 0; i < s1.Length; i++)
        {               
            if (s1[i] == s2[i]) continue;
            for (int j = -1; j < 2; j = j + 2)
            {
                var aOrb = j == -1 ? s1[i] : s2[i];
                if (bucket.ContainsKey(aOrb))
                {
                    bucket[aOrb] += j;
                    if (bucket[aOrb] == 0)
                    {
                        bucket.Remove(aOrb);
                    }
                }
                else
                {
                    bucket.Add(aOrb, j);
                }
            }
        }
        return bucket.Count == 0;
    }
    static void Main()
    {
        Console.WriteLine(IsAnagram(
            "tom marvolo riddle",
            "i am lord voldemort"));
    }
    static bool IsAnagram(string word, string dest)
    {
        var w = WordSpliter(word);
        var d = WordSpliter(dest);
        return w.Count == d.Count && w.Count == w.Where(x => d.Contains(x)).ToList().Count;
    }
    static List<(char Key, int Count)> WordSpliter(string word)
    {
        return word.Replace(" ", "").ToLower().GroupBy(c => c).Select(x => (
           x.Key,
           Count: x.Count()
       )).ToList();
    }

如果时间有限,这是一个更好/更有效的解决方案:

bool CheckAnagram(string str1, string str2)
{
    if(str1.Length != str2.Length)
        return false;
    if(str1 == str2)
        return true;
    // based on 128 ASCII characeters. 
    // You can change the paramter depending on requirement
    int charLength = 128; 
    int[] counter = new int[charLength];
    for(int i=0; i<str1.Length; i++)
    {
        counter[str1[i]-'a']++;
        counter[str2[i]-'a']--;
    }
    for (int c = 0; c < charLength; c++) 
    {
        if(counter[c] != 0) return false;
    }
    return true;
}

此解决方案在codestandd.net上被接受

public bool IsAnagram(string one, string two)
    {
        if(one.ToLower().Equals(two.ToLower()))
            return true;
    
        var array1 = one.ToCharArray();
        var array2 = two.ToCharArray();
        
        Array.Sort(array1);
        Array.Sort(array2);
        
        return array1 == array2;
    }
    public static bool IsAnagram(this string a, string b)
    {
        //check the length are not same ? not Anagram
        if (a.Length != b.Length)
            return false;
        // check both the strings are same ? Angram
        if (a == b)
            return true;
        // Sort the characters alphabetically and compare them to one another.
        return a.OrderBy(c => c).SequenceEqual(b.OrderBy(c => c));
    }

此解决方案将检查恰好1次的变位(O(Cn),其中C = 1)

    public static bool IsAnagram(string s1, string s2) {
        if (s1.Length != s2.Length)
            return false;
        int i = -1;
        var chars = new Dictionary<char, int> ();
        Func <char, int, int, int> updateCount = (c, side, pdiff) => {
            int count = 0;
            chars.TryGetValue (c, out count);
            var newCount = count + side;
            chars[c] = newCount;
            if (count == 0)
                return pdiff + 1;
            else if (newCount == 0)
                return pdiff - 1;
            else
                return pdiff;
        };
        int diff = 0;
        foreach (var c1 in s1) {
            i++;
            var c2 = s2 [i];
            if (c1 == c2)
                continue;
            diff = updateCount(c1, 1, diff);
            diff = updateCount(c2, -1, diff);
        }
        return diff == 0;
    }
    public static void Main (string[] args)
    {
        string s1 = "asd";
        string s2 = "ads";
        Console.WriteLine (IsAnagram(s1, s2));
    }

对于不区分大小写的情况,您可以尝试:

public bool IsAnagram(string firstString, string secondString)
        {
            List<char> firstlist = new List<char>();
            firstlist.AddRange(firstString);
            List<char> secondlist = new List<char>();
            secondlist.AddRange(secondString);
            if (secondlist.Count != firstlist.Count)
            {
                return false;
            }
            while (firstlist.Count != 0 && secondlist.Count != 0)
            {
                foreach (var sec in secondlist)
                {
                    foreach (var fir in firstlist)
                    {
                        if (char.ToUpperInvariant(sec) == char.ToUpperInvariant(fir))
                        {
                            firstlist.Remove(fir);
                            break;
                        }
                    }
                    secondlist.Remove(sec);
                    break;
                }
            }
            if (firstlist.Count == secondlist.Count)
                return true;
            return false;          
        }

try this

static bool isAnagrams(string str1,string st)
{
    string str1 = "reaad";
    string str2 = "Daaer";
    char[] t = str1.ToCharArray();
    var kt = t.Distinct();
    string pattern = @"e";
    // Create a Regex  
    Regex rg = new Regex(pattern);
    Console.WriteLine(rg.Match(str1).Value);
    foreach (var item in kt)
    {
        string pat = item.ToString();
        Regex r = new Regex(pat,RegexOptions.IgnoreCase);
        if (r.Matches(str1).Count != r.Matches(str2).Count)
        {
            return false;
        }
    }
    return true;
}
char[] fArr = new char[First.Length];
    char[] sArr = new char[Second.Length];
    fArr = First.ToLower().ToCharArray();
    sArr= Second.ToLower().ToCharArray();
    if (fArr.Length == sArr.Length)
    {
       Array.Sort(fArr);
        Array.Sort(sArr);
    }

    return new string(fArr) == new string(sArr) ? true : false;

我有一个字符串列表的解决方案(不只是两个字符串)。如果你对它或其他任何一个感兴趣,你可以使用它。

给定一个字符串数组,删除每一个由先前字符串变形的字符串,然后按存储顺序返回剩下的字符串。

private static List<string> GencoAnagrams(List<string> textList)
    {
        var listCount = textList.Count;
        if (listCount == 1) return textList;
        for (var j = 1; j < listCount; j++)
        {
            for (var i = 0; i < j; i++)
            {
                if (string.Concat(textList[j].OrderBy(x => x)).Equals(string.Concat(textList[i].OrderBy(y => y))))
                {
                    textList.RemoveAt(j);
                    --listCount;
                    --j;
                    if (listCount == 1) break;
                }
            }
            if (listCount == 1) break;
        }
        return textList;
    }

我也感谢"Thomas Krojer"的回答,他一开始对我很有帮助。

如果(String.Concat (

。OrderBy(c => c)).Equals(String.Concat(b))=>

0 (n)解

public bool Anagram(string s , string p)
{
    char[] dS = s.ToCharArray();
    char[] dP = p.ToCharArray();
    Array.Sort(dS);
    Array.Sort(dP);
    string rS = new string(dS);
    string rP = new string(dP);
    return rS == rP;
}
class Anagrams
{
    static void Main()
    {
        // 1
        // Read and sort dictionary
        var d = Read();
        // 2
        // Read in user input and show anagrams
        string line;
        while ((line = Console.ReadLine()) != null)
        {
            Show(d, line);
        }
    }
    static Dictionary<string, string> Read()
    {
        var d = new Dictionary<string, string>();
        // Read each line
        using (StreamReader r = new StreamReader("enable1.txt"))
        {
            string line;
            while ((line = r.ReadLine()) != null)
            {
                // Alphabetize the line for the key
                // Then add to the value string
                string a = Alphabetize(line);
                string v;
                if (d.TryGetValue(a, out v))
                {
                    d[a] = v + "," + line;
                }
                else
                {
                    d.Add(a, line);
                }
            }
        }
        return d;
    }
    static string Alphabetize(string s)
    {
        // Convert to char array, then sort and return
        char[] a = s.ToCharArray();
        Array.Sort(a);
        return new string(a);
    }
    static void Show(Dictionary<string, string> d, string w)
    {
        // Write value for alphabetized word
        string v;
        if (d.TryGetValue(Alphabetize(w), out v))
        {
            Console.WriteLine(v);
        }
        else
        {
            Console.WriteLine("-");
        }
    }
}
string one = "aabba";
        string two = "bbaaa";
        int check = 0;
        List<char> oneList = one.ToCharArray().ToList();
        List<char> twoList = two.ToCharArray().ToList();
        foreach (var letter in oneList /* the principal */)
        {
            if (twoList.Contains(letter))
            {
                check++;
            }
        }
        if (check == twoList.Count)
        {
            return true;
        }
        else
        {
            return false;
        }