kmp算法
求能否配的上的模板
const int maxn=1e6+10;
int nex[maxn];//记录的是前缀和后缀最大公共部分的下一位坐标,由数组前后缀最大公共长度右移一位得出
char p[maxn],s[maxn];
void init()
{
fill(nex,nex+maxn,0);
//fill(p,p+maxn,'');
}
void get_nex()
{
int j=-1,i=0;//因为求next数组是由前缀和后缀共同求出,切next[1]没求出,所以i要从-1开始,j从零开始
nex[0]=-1;
/*
这样写更容易理解
int j=0,i=1;
nex[0]=-1;
nex[1]=0;
*/
int len=strlen(p);
while(i<len)
{//i=-1表示不存在公共前缀和后缀 ,那么就让下一位和0进行匹配
if(j==-1||p[i]==p[j])//i==-1说明如果第j位匹配不到,则让i=-1,是j+1的位置与0匹配。
{
i++;
j++;
nex[i]=j;
}
else
{
j=nex[j];
}
}
}
int kmp()
{
int i=0,j=0;
int ans=0;
int slen=strlen(s);
int plen=strlen(p);
while(i<slen&&j<plen)
{//j=-1表示,s串和p串i,j之前的不存在能匹配的
if(j==-1||s[i]==p[j])
{
i++;
j++;
}
else
{
j=nex[j];
}
}
if(j==plen)
return i-j;//返回的是下标位置
else
return -1;
}
如果题目中询问可以匹配多少次,那么只需要修改一下kmp算法即可
int kmp()
{
int ans=0;
int i=0,j=0;
int ans=0;
int slen=strlen(s);
int plen=strlen(p);
while(i<slen)
{//j=-1表示,s串和p串i,j之前的不存在能匹配的
if(j==-1||s[i]==p[j])
{
i++;
j++;
}
else
{
j=nex[j];
}
if(j==slen)
{
j=nex[j-1];
i--;
ans++;
}
}
return ans;
}