学习笔记(kmp)

开始学习与字符串有关的算法:
kmp:用于比较字符串a是否是b子串的算法。
设a的长度为n,b的长度为m
暴力求解时间是n*m,而kmp是n+m;
可以大幅度减少时间复杂度
求出字符串子串中前缀和后缀相等的部分的个数
代码:

#include<bits/stdc++.h>
using namespace std;
int next[10005];
void cal_next(string str,int len){
 next[0]=-1;
 int k=-1;
 for(int i=1;i<=len-1;i++){
  while(k>-1&&str[k+1]!=str[i])
  k=next[k];
  if(str[k+1]==str[i])
  k++;
  next[i]=k;
 }
} 
int main(){
  string a;
  cin>>a;
  int len=a.length();
  cal_next(a,len);
  for(int i=0;i<len;i++){
   printf("i=%d,next=%d\n",i,next[i]);
  }
}

假设现在文本串S匹配到 i 位置,模式串P匹配到 j 位置
如果j = -1,或者当前字符匹配成功(即S[i] == P[j]),都令i++,j++,继续匹配下一个字符;
如果j != -1,且当前字符匹配失败(即S[i] != P[j]),则令 i 不变,j = next[j]。此举意味着失配时,模式串P相对于文本串S向右移动了j - next [j] 位。

int KMP(char *str, int slen, char *ptr, int plen)
{
  int *next = new int[plen];
  cal_next(ptr, next, plen);//计算next数组
  int k = -1;
  for (int i = 0; i < slen; i++)
  {
      while (k >-1&& ptr[k + 1] != str[i])//ptr和str不匹配,且k>-1(表示ptr和str有部分匹配)
          k = next[k];//往前回溯
      if (ptr[k + 1] == str[i])
          k = k + 1;
      if (k == plen-1)//说明k移动到ptr的最末端
      {
          //cout << "在位置" << i-plen+1<< endl;
          //k = -1;//重新初始化,寻找下一个
          //i = i - plen + 1;//i定位到该位置,外层for循环i++可以继续找下一个(这里默认存在两个匹配字符串可以部分重叠),感谢评论中同学指出错误。
          return i-plen+1;//返回相应的位置
      }
  }
  return -1;  
}

————————————————
版权声明:本文为CSDN博主「路漫远吾求索」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接

猜你喜欢

转载自blog.csdn.net/Nefeertari/article/details/107614301
今日推荐