如何在c#中检查变位字符串
本文关键字:字符串 检查 | 更新日期: 2023-09-27 18:14:34
给定两个字符串A和B,检查它们是否是字谜
如果一个字符串可以通过重新排列另一个字符串的字母得到,则称两个字符串为字谜。
字谜的例子有
-
dog, god
-
abac, baac
-
123, 312
abab, aaba
和dab, baad
不是字谜。
输入的第一行是测试用例T的数量。后面跟着T行,每行有两个空格分隔的字符串A和B;
对于每个测试用例,如果它们是字谜,则打印"YES",否则打印"NO"。(没有引号)
- 1 <= T <= 10
- A和B都只包含小写拉丁字母"A"到"z"和数字0 ~ 9
- 每个字符串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;
}
这是你的解决方案吗?
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;
}