我正在编写代码来查找给定单词的所有子词。它需要一个WordGame,它的结构中有一个字典(使用树实现)。
它应该产生的是一个单词的所有子词,这些子词在我上面提到的词典中。但是,例如,单词是" libels",输出是
"lib"
"libel"
"libels"
"libs"
代码是
void swap (char *x, char *y)
{
char temp;
temp = *x;
*x = *y;
*y = temp;
}
void subWords(char *a, int i, int n, WordGame game)
{
//This algorithm first finds all the anagrams of a 6 letter word.
//For each anagram it then finds all the 3/4/5/6 in the dicitonary.
//To find the 3/4/5/6 letter words it first finds all the 3 letter words
//then the 4 letter words and so on.
//For example, to find 3 letter words from the word ABCDEF it does this
// A B C D E F
// |_| |_| |_| = ABC
// A B C D E F
// |_| |_| |_| = BCD
//etc
//Since it does this for all the anagrams of the 6 letter word it should
//find all the 3 letter subwords of the 6 letter word then for the 4 letter
//subwords and so on.
int j;
int k;
int m;
if (i == n){ //When an anagram is foumd
for(k = 3; k <= 6; k++){ //Used for finding subwords of lengths 3-6
char str[k];
for(m = 0; m + k <= 6; m++){ //Used for making sure we don't step
strncpy(str,a+m,k); //out of array and moving along array
str[k] = '\0';
if(DictFindWord(game->dict,str) !=0){
if(ListSearch(game->aWords[k],str) == NULL){
ListInsertInOrder(game->aWords[k],str);
printf("%s\n",str);
}
}
}
}
}
else
{
for (j = i; j <= n; j++)
{
swap((a+i), (a+j));
subWords(a, i+1, n, game);
swap((a+i), (a+j));
}
}
}
似乎找到了该词的初始状态的子词,即l-i-b-e-l-s。它没有找到胆汁,因为它不在单词的初始状态,我的代码应该找到所有字谜的子字,而且它似乎找不到单词的排列。这使得我的subWord函数看起来不会产生初始单词的字谜,但这不是真的,因为当我用这个运行我的代码时:
int j;
if (i == n){ //When an anagram is foumd
printf("%s\n",a);
}
else
{
for (j = i; j <= n; j++)
{
swap((a+i), (a+j));
subWords(a, i+1, n, game);
swap((a+i), (a+j));
}
}
}
它会打印该单词的所有可能排列。 ListSearch,InsertInOrder函数是提供的函数,很可能是正确的。
注意:当我调用函数时,我调用函数subWords,我用n调用它,它比数组大小少一个,所以我不会访问数组中的元素。
答案 0 :(得分:1)
您的代码中有一些越界访问。
首先,您的“原始”版本(仅打印排列)对我不起作用,因为您访问元素a[n]
。数组索引包括0,但不包括数组长度。循环如:
for (j = i; j <= n; j++) ...
其中j
用于索引长度为n
的数组,应该响起一些警钟。所以:
} else {
for (j = i; j < n; j++) {
swap((a + i), (a + j));
subWords(a, i + 1, n);
swap((a + i), (a + j));
}
}
辅助数组str
也是如此。它在最后保存k
个字符加上空终止符。使用
str[k] = '\0';
但要使其工作,char数组str
必须有一个元素超过k
,否则你在数组结束后访问该元素:
char str[k + 1];
(算法本身效率很低。对于"libels"
,你最终生成6!= 720个排列,然后检查每个排列的所有4 + 3 + 2 + 1 = 10个子词。你最终检查了一些几次,而不仅仅是因为你的话有两个L's。
您可以通过首先查找原始子串然后填充子串来减少检查次数。如果原始单词具有唯一字母,这至少可以保证您不会对一个单词进行多次检查。对于诽谤,这会将你的支票减少到4·3! + 3·4! + 2·5! + 1·6! = 1054次检查。
如果你必须针对同一个字典检查多个单词,即使这样也会很慢。如果你能够以一种快速找到所有可以由1b,1 e,1 i,2 l和1 s组成的单词的方式存储你的字典,你可以加速你的算法。)