KMP
在s中寻找p(找到第一次出现的位置)
void find_next(char *p)
{
int h=strlen(p);
int k=-1;
int j=0;
next[j]=k;
while(j<h)
{
if(k==-1||p[k]==p[j])
{
j++;
k++;
next[j]=k;
}
else
k=next[k];
}
return ;
}
int kmp(char *s,char *p)
{
int hs=strlen(s);
int hp=strlen(p);
int i=0;
int j=0;
while(i<hs&&j<hp)
{
if(j==-1||s[i]==p[j])
{
i++;
j++;
}
else
j=next[j];
}
if(j==hp)
return i-j;
else
return -1;
}
求所有的子串位置
在next数组里,最后一位是不包括最后一个数,前面的字符串的最长相同前后缀长度,如果要求所有的,就需要遍历到最后一位+1的位置,遍历到这里其实是整个p字符串最长相同前后缀长度。题目与代码如下
P3375 【模板】KMP字符串匹配
传送门
#include<iostream>
#include<stdio.h>
#include<string>
using namespace std;
int next[1000100];
void find_next(string p)
{
int k=-1;
int j=0;
next[0]=-1;
while(j<p.size())
{
if(k==-1||p[k]==p[j])
{
k++;
j++;
// if(j!=p.size()&&p[k]==p[j])
// next[j]=next[k];
// else
next[j]=k;
}
else
k=next[k];
}
return ;
}
void Kmp(string s,string p)
{
int i=0,j=0;
int slen=s.size();
int plen=p.size();
while(i<slen&&j<plen)
{
if(j==-1||s[i]==p[j])
{
i++;
j++;
if(j==plen)
{
printf("%d\n",i-j+1);
j=next[j];
}
}
else
j=next[j];
}
return ;
}
int main()
{
string s,p;
cin>>s>>p;
find_next(p);
Kmp(s,p);
for(int i=1;i<=p.size();i++)
cout<<next[i]<<' ';
}
/*
ABABABAB
ABAB
*/
next数组优化
void find_next(string p)
{
int k=-1;
int j=0;
next[0]=-1;
while(j<p.size())
{
if(k==-1||p[k]==p[j])
{
k++;
j++;
if(j!=p.size()&&p[k]==p[j])
next[j]=next[k];
else
next[j]=k;
}
else
k=next[k];
}
return ;
}