未获得预期的输出 - 查找单词的所有子词

时间:2015-05-23 05:47:04

标签: c debugging

我正在编写代码来查找给定单词的所有子词。它需要一个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调用它,它比数组大小少一个,所以我不会访问数组中的元素。

1 个答案:

答案 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个字符加上空终止符。使用

正确设置null终止符
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组成的单词的方式存储你的字典,你可以加速你的算法。)