首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >纯C++的Knuth-Morris-Pratt实现

纯C++的Knuth-Morris-Pratt实现
EN

Stack Overflow用户
提问于 2012-06-29 15:17:43
回答 1查看 5.9K关注 0票数 0

我有下一个KMP实现:

代码语言:javascript
复制
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int kmp(char substr[], char str[])
{
   int i, j, N, M;

   N = strlen(str);
   M = strlen(substr);

   int *d = (int*)malloc(M * sizeof(int));
   d[0] = 0;

   for(i = 0, j = 0; i < M; i++)
   {
      while(j > 0 && substr[j] != substr[i])
      {
         j = d[j - 1];
      }

      if(substr[j] == substr[i])
      {
         j++;
         d[i] = j;
      }
   }

   for(i = 0, j = 0; i < N; i++)
   {
      while(j > 0 && substr[j] != str[i])
      {
         j = d[j - 1];
      }

      if(substr[j] == str[i])
      {
         j++;
      }

      if(j == M)
      {
         free(d);
         return i - j + 1;
      }
   }

   free(d);

   return -1;
}

int main(void)
{
   char substr[] = "World",
      str[] = "Hello World!";

   int pos = kmp(substr, str);

   printf("position starts at: %i\r\n", pos);

   return 0;
}

你可以在这里测试它:http://liveworkspace.org/code/d2e7b3be72083c72ed768720f4716f80

它在小字符串上工作得很好,我已经用一个大循环对它进行了测试,在这种情况下一切都很好。

但是,如果我将正在搜索的子字符串和完整字符串更改为以下内容:

代码语言:javascript
复制
char substr[] = "%end%",
str[] = "<h1>The result is: <%lua% oleg = { x = 0xa }
         table.insert(oleg, y) oleg.y = 5 print(oleg.y) %end%></h1>";

只有在第一次尝试之后,此实现才会失败...

请,您可以帮助我修复KMP的实现,使算法与这些数据在字符串中工作…

EN

回答 1

Stack Overflow用户

发布于 2012-06-29 18:07:52

在一个地方,你偏离了你的来源,来源有

代码语言:javascript
复制
while(j>0 && p[j]!=p[i]) j = d[j-1];
    if(p[j]==p[i])
        j++;
        d[i]=j;

当你有了

代码语言:javascript
复制
while(j > 0 && substr[j] != substr[i])
{
    j = d[j - 1];
}
if(substr[j] == substr[i])
{
    j++;
    d[i] = j;
}

被来源的缩进所欺骗。在源代码中,if()分支周围没有大括号,因此只有增量j++;if控制;d[i] = j;是无条件的。

然后,源文件出现错误,可能是由于索引的异常使用所致。设置数组的正确方法是

代码语言:javascript
复制
int *d = (int*)malloc(M * sizeof(int));
d[0] = 0;

for(i = 1, j = 0; i < M; i++)
{
    while(j > 0 && substr[j-1] != substr[i-1])
    {
        j = d[j - 1];
    }

    if(substr[j] == substr[i])
        j++;
    d[i] = j;
}

但这很令人困惑,因为这里的设置使用索引i-1j-1以及ij来确定d[i]。通常的实现方式是不同的;它的实现方式是in C#。因为这是您在大多数资源中找到的形式,所以更容易说服自己相信它的正确性。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11257652

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档