我完全难过了。问题是:鉴于你有一个字符串,如#34; thisisasentence"函数isWord()如果是英文单词则返回true,我会卡在"这是一个发送的"
我如何以递归方式返回并跟踪每次我的位置?
答案 0 :(得分:1)
您需要backtracking,这可以通过递归轻松实现。重点观察是,当您准备好返回解决方案时,您无需跟踪过去的位置。
当满足以下条件之一时,您有一个有效的“拆分”:
w
为空(基本情况)或w
分为子字符串p
和s
,以便p+s=w
,p
为单词,{{1} }可以分成一个句子(递归调用)。实现可以在找到成功拆分时返回单词列表,或者在找不到时找到s
。基本案例将始终返回一个空列表;递归情况,在找到导致null
的非空返回的p
,s
拆分后,构造一个列表,其中s
前缀为从递归返回的列表调用
递归的情况下会有一个循环,尝试p
的所有可能的前缀。为了加快速度,循环可以在到达与字典中最长的单词长度相等的前缀时终止。例如,如果最长的单词有12个字符,则您知道尝试13个字符或更长的前缀不会导致匹配,因此您可以缩短枚举次数。
答案 1 :(得分:0)
只是添加上面的答案。
根据我的经验,很多人在看到递归算法的“线性化”版本时会更好地理解递归,这意味着«作为堆栈上的循环实现»。线性化适用于任何递归任务。
假设isWord()
有两个参数(第一个:要测试的字符串;第二个:它的长度)并返回一个布尔兼容的值,后退的C实现如下:
void doSmth(char *phrase, int *words, int total) {
int i;
for (i = 0; i < total; ++i)
printf("%.*s ", words[i + 1] - words[i], phrase + words[i]);
printf("\n");
}
void parse(char *phrase) {
int current, length, *words;
if (phrase) {
words = (int*)calloc((length = strlen(phrase)) + 2, sizeof(int));
current = 1;
while (current) {
for (++words[current]; words[current] <= length; ++words[current])
if (isWord(phrase + words[current - 1],
words[current] - words[current - 1])) {
words[current + 1] = words[current];
current++;
}
if (words[--current] == length)
doSmth(phrase, words, current); /** parse successful! **/
}
free(words);
}
}
可以看出,对于每个单词,使用一对堆栈值,第一个是当前单词的第一个字符的偏移量,而第二个是当前字符恰好在当前字符之后的潜在偏移量word`s last one(因此是下一个单词的第一个字符)。当前单词的第二个值(其对位于我们的«stack»顶部的那个)将遍历短语中剩下的所有字符。
当一个单词被接受时,新的第二个值(等于当前,仅查看其后的位置)被推入堆栈,使前者成为新对中的第一个。如果当前单词(刚刚找到的单词)完成短语,则执行一些有用的操作;见doSmth()
。
如果我们的短语的剩余部分中没有可接受的单词,则当前单词被认为是不合适的,并且其第二个值从堆栈中被丢弃,有效地重复搜索前一个起始位置处的单词,而结束位置现在比之前接受的那个词更远。