我通常不会这样做,但我想出了一个更好的解决方案来解决您的问题,它值得自己回答!这个AnagramSolver
解决方案比我的其他答案更优化,因为它不会创建单词的每一个单一置换,并且字典查找是非常优化的。试试看:
用法示例:
string[] dictionary = ReadDictionary(...);
var solver = new AnagramSolver(dictionary);
int minimumLength = 1;
IEnumerable<string> results = solver.SolveAnagram("AEMNS", minimumLength);
// Output the results:
foreach (var result in results)
{
Console.WriteLine(result);
}
// Output example:
// "NAMES", "MANES", "MEANS", "AMEN", "MANE", "MEAN", "NAME", "MAN", "MAE", "AM", "NA", "AN", "MA", "A",
代码:
public class AnagramSolver
{
public AnagramSolver(IEnumerable<string> dictionary)
{
// Create our lookup by keying on the sorted letters:
this.dictionary = dictionary.ToLookup<string, string>(SortLetters);
}
private ILookup<string, string> dictionary;
public IEnumerable<string> SolveAnagram(string anagram, int minimumLength)
{
return CreateCombinations(anagram, minimumLength)
// Sort the letters:
.Select<string, string>(SortLetters)
// Make sure we don't have duplicates:
.Distinct()
// Find all words that can be made from these letters:
.SelectMany(combo => dictionary[combo])
;
}
private static string SortLetters(string letters)
{
char[] chars = letters.ToCharArray();
Array.Sort(chars);
return new string(chars);
}
/// <summary> Creates all possible combinations of all lengths from the anagram. </summary>
private static IEnumerable<string> CreateCombinations(string anagram, int minimumLength)
{
var letters = anagram.ToCharArray();
// Create combinations of every length:
for (int length = letters.Length; length >= minimumLength; length--)
{
yield return new string(letters, 0, length);
// Swap characters to form every combination:
for (int a = 0; a < length; a++)
{
for (int b = length; b < letters.Length; b++)
{
// Swap a <> b if necessary:
char temp = letters[a];
if (temp != letters[b]) // reduces duplication
{
letters[a] = letters[b];
letters[b] = temp;
yield return new string(letters, 0, length);
}
}
}
}
}
}
这里的算法摘要:
的基本思想是,每一套字谜从派生同一组字母。
如果我们对字母进行排序,我们可以将多组字形组合在一起。
我从Algorithm for grouping anagram words得到了这个想法。
例如,可以在“AEMNS”上键入一组字符(“NAMES”,“MANES”,“MEANS”)。
因此,一旦我们创建了我们的字典查找,解决这个咒语的过程非常简单快捷 - 只需对字谜的字母进行排序并执行查找即可。
下一个挑战是找到所有“较小”的字谜 - 例如,找到“名称”,“SANE”,“MAN”,“AN”,“A”等。
这可以通过发现所有组合的谜语。
组合比排列更容易找到。不需要递归。我用3个循环和简单的交换实现了完整的组合!花了一段时间才算正确的算法,但现在它已经被清理干净了,非常漂亮。
对于找到的每个组合,我们必须再次对这些字母进行排序并执行查找。
这给了我们所有可能的解决方案的字谜!
你忘记了“家庭作业”标签吗? –
即使您没有任何代码包含在您的问题中,您是否可以显示您尝试创建的算法的一些示例输入和输出? – CoderDennis
@Muad这不是一门功课..即时通讯练习如何编程以及.. 样品输入: 模式:2V-5C 快报:AOLPNMC 组合: AOL OLP PAL PAN ... PLAM PALM等..被发现 接话: PALM 计划 ...这将列出所有在系统词典中找到的话..比较生成到系统字典中的所有组合,如果匹配则它将被列在Words Found Listbox中。 .. – Rex