KMP
入门讲解:可以点我哦OAO
模板:
#include<bits/stdc++.h>
using namespace std;
char s[1005],p[1005]; ///s是主串,p是子串
int Next[1005];
void getext()
{
int plen=strlen(p);
int i=0,j=-1;
Next[0]=-1;
while(i<plen)
{
if(j==-1||p[i]==p[j]) ///匹配成功
{
i++;
j++;
Next[i]=j;
}
else j=Next[j]; ///匹配失败,回溯
}
}
bool kmp()
{
int slen=strlen(s);
int plen=strlen(p);
int i=0,j=0;
while(i<slen&&j<plen)
{
if(j==-1||s[i]==p[j]) ///匹配成功,i++,j++
{
i++;j++;
}
else j=Next[j]; ///匹配失败,回溯
}
if(j==plen) return true; ///j=plen代表子串已经全部匹配
return false;
}
int main()
{
cin>>s>>p;
getext();
if(kmp()) cout<<"模式串p是主串s的子串";
else cout<<"模式串p不是主串s的子串";
return 0;
}
入门题目:点我传送门
题解代码:
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int MMAX=1e6+5;
char s1[MMAX],s2[MMAX];
int Next[MMAX];
void getNext()
{
int i=0,j=-1;
Next[0]=-1;
int len=strlen(s2);
while(i<len)
{
if(j==-1||s2[i]==s2[j])
{
i++;
j++;
Next[i]=j;
}
else j=Next[j];
}
return ;
}
void KMP()
{
int i=0,j=0;
int len=strlen(s1),le=strlen(s2);
while(i<len) ///注意限制条件
{
if(j==-1||s2[j]==s1[i])
{
i++;
j++;
if(j==le) ///匹配成功
{
printf("%d\n",i-j+1); ///字符串从0开始,所以要多+1
j=Next[j];
}
}
else j=Next[j];
}
}
int main()
{
scanf("%s%s",s1,s2);
getNext(); ///处理Next数组
KMP(); ///遍历
int len=strlen(s1),le=strlen(s2);
for(int i=0;i<le;i++) ///输出前缀最长的border长度
printf("%d ",Next[i+1]);
printf("\n");
return 0;
}