- 课堂交流区
- 帖子详情
89
回复
-
<p>要让 KMP 函数返回模式在文本中的子串,可以修改函数的返回类型为字符串类型。同时,在 KMP 函数内部要记录子串在文本中的起始和终止下标,然后返回这个子串。下面是一个简单的修改版本:</p><p><br ></p><p><br ></p><p>#include <iostream></p><p>#include <cstring></p><p>using namespace std;</p><p><br ></p><p>string KMP(string text, string pattern)</p><p>{</p><p> int tlen = text.size();</p><p> int plen = pattern.size();</p><p> int fail[plen + 1];</p><p> memset(fail, -1, sizeof(fail));</p><p><br ></p><p> for (int j = 1; j < plen; ++j) {</p><p> int i = fail[j - 1];</p><p> while (pattern[j] != pattern[i + 1] && i >= 0) i = fail[i];</p><p> if (pattern[j] == pattern[i + 1]) fail[j] = i + 1;</p><p> }</p><p><br ></p><p> int i = 0, j = 0;</p><p> while (i < tlen && j < plen) {</p><p> if (text[i] == pattern[j]) {</p><p> ++i; ++j;</p><p> } else if (j == 0) {</p><p> ++i;</p><p> } else {</p><p> j = fail[j - 1] + 1;</p><p> }</p><p> }</p><p><br ></p><p> if (j == plen) {</p><p> return text.substr(i - plen, plen);</p><p> } else {</p><p> return "not found";</p><p> }</p><p>}</p><p><br ></p><p>int main()</p><p>{</p><p> string text = "ABCABCABCABD";</p><p> string pattern = "ABCABD";</p><p> cout << KMP(text, pattern) << endl; // output: ABCABD</p><p> return 0;</p><p>}</p><p><br ></p><p>在 main 函数里,我们用 cout 输出 KMP 函数返回的字符串。这样,就可以在调用 KMP 函数后方便地输出子串了。</p><p><br ></p><p><br ></p><p><br ></p><p><br ></p><p><br ></p><p>riqilang wu</p><p>如果将 match[j] 定义为 pattern[0...j] 首尾匹配子串的最大长度,该如何修改 KMP 和 BuildMatch 的实现?</p><p>如果将 match[j] 定义为 pattern[0...j] 首尾匹配子串的最大长度,可以按照以下步骤完成 KMP 函数和 BuildMatch 函数的实现:</p><p><br ></p><p><br ></p><p><br ></p><p><br ></p><p>在 KMP 函数中,对于所有 j < plen, match[j] 的值就是 fail[j] 的值加一(由于 fail 数组存储的是最后一个字符的最长公共前后缀长度,因此需要加一)。</p><p><br ></p><p><br ></p><p><br ></p><p><br ></p><p>BuildMatch 函数的实现也要相应地改变。在计算 fail 数组的过程中,可以顺便求出 match 数组的元素值。具体来说,只需要在 if (pattern[j] == pattern[i + 1]) 的分支中添加 match[j] = match[i] + 1; 的语句即可。</p><p><br ></p><p><br ></p><p><br ></p><p><br ></p><p>下面是 KMP 函数和 BuildMatch 函数的修改版本:</p><p><br ></p><p><br ></p><p>void BuildMatch(string pattern, int* fail, int* match)</p><p>{</p><p> int plen = pattern.size();</p><p> fail[0] = -1;</p><p> match[0] = -1;</p><p><br ></p><p> for (int j = 1; j < plen; ++j) {</p><p> int i = fail[j - 1];</p><p> while (pattern[j] != pattern[i + 1] && i >= 0) i = fail[i];</p><p> if (pattern[j] == pattern[i + 1]) {</p><p> fail[j] = i + 1;</p><p> match[j] = match[i] + 1;</p><p> } else {</p><p> fail[j] = -1;</p><p> match[j] = -1;</p><p> }</p><p> }</p><p>}</p><p><br ></p><p>int KMP(string text, string pattern)</p><p>{</p><p> int tlen = text.size();</p><p> int plen = pattern.size();</p><p> int fail[plen], match[plen];</p><p> memset(fail, -1, sizeof(fail));</p><p> memset(match, -1, sizeof(match));</p><p><br ></p><p> BuildMatch(pattern, fail, match);</p><p><br ></p><p> int i = 0, j = 0;</p><p> while (i < tlen && j < plen) {</p><p> if (text[i] == pattern[j]) {</p><p> ++i; ++j;</p><p> } else if (j == 0) {</p><p> ++i;</p><p> } else {</p><p> j = fail[j - 1] + 1;</p><p> }</p><p> }</p><p><br ></p><p> if (j == plen) {</p><p> return match[j - 1];</p><p> } else {</p><p> return -1;</p><p> }</p><p>}</p><p><br ></p><p>在 KMP 函数中,我们新增了一个 match 数组来存储首尾匹配子串的最大长度。BuildMatch 函数在计算 fail 数组的同时,顺便计算 match 数组的元素值。在调用 KMP 函数时,我们得到的匹配结果就是首尾匹配子串的最大长度,如果匹配失败则返回 -1。</p><p><br ></p>添加评论
-
通过学习该门课程,我学习到了很多有关于该门课程的知识,很大程度上提升的我对该领域的兴趣,加强了课外兴趣,培养了创新能力,学到了很多知识,收获颇多!!!!添加评论
-
通过学习该门课程,我学习到了很多有关于该门课程的知识,很大程度上提升的我对该领域的兴趣,加强了课外兴趣,培养了创新能力,学到了很多知识,收获颇多!!!!添加评论
-
1添加评论
-
1添加评论
-
1添加评论
-
1添加评论
-
1添加评论
-
1添加评论
-
通过学习该门课程,我学习到了很多有关于该门课程的知识,很大程度上提升的我对该领域的兴趣,加强了课外兴趣,培养了创新能力,学到了很多知识,收获颇多!!!!添加评论
-
通过学习该门课程,我学习到了很多有关于该门课程的知识,很大程度上提升的我对该领域的兴趣,加强了课外兴趣,培养了创新能力,学到了很多知识,收获颇多!!!!添加评论
-
通过学习该门课程,我学习到了很多有关于该门课程的知识,很大程度上提升的我对该领域的兴趣,加强了课外兴趣,培养了创新能力,学到了很多知识,收获颇多!!!!添加评论
点击加载更多
到底啦~