算法的目的
kmp算法:KMP算法是一种改进的字符串匹配算法,利用匹配失败后的信息,尽可能地减少模式串与主串的匹配次数以达到快速匹配的目的。
例如:在主串t中寻找模式串w出现的位置,若用暴力的算法要对主串中的每个位置对w进行匹配,故时间复杂度为o(mn),而在KMP算法中,在匹配失败时,通过最大的移动模式串,以减少匹配次数,达到o(m+n)的复杂度。
算法的思想
实现一个next()函数,在已经匹配的模式串子串中,找出最长的相同的前缀和后缀,然后移动使它们重叠,然后在从上次匹配失败的地方进行匹配,这样就减少了匹配次数,增加了效率。
模板题
HDU 1711 Number Sequence
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
int a[1000005],b[10005];
int next[10005];
void kmp(int n,int m)
{
int i=0;
int j=0;
while(j<n)
{
if(i==m-1&&a[j]==b[i])
{
j++;
i++;
printf("%d\n",j-i+1);
return ;
}
if(a[j]==b[i])
{
i++;
j++;
}
else
{
i=next[i];
if(i==-1)
{
i++;
j++;
}
}
}
printf("-1\n");
return ;
}
void getnext(int m)
{
next[0]=-1;
int i=0;
int len=-1;
while(i<m)
{
if(len==-1||b[i]==b[len])
{
i++;
len++;
next[i]=len;
}
else
{
len=next[len];
}
}
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n,m;
scanf("%d%d",&n,&m);
memset(a,'\0',sizeof(a));
memset(b,'\0',sizeof(b));
for(int i=0;i<n;i++)
{
scanf("%d",&a[i]);
}
for(int i=0;i<m;i++)
{
scanf("%d",&b[i]);
}
getnext(m);
kmp(n,m);
}
return 0;
}
HDU 1686 Oulipo
#include<bits/stdc++.h>
using namespace std;
char w[10005],t[1000005];
int next[10005];
void getnext(char w[],int nexto[],int m)
{
nexto[0]=-1;
int i=0;
int j=-1;
while(i<m)
{
if(j==-1||w[i]==w[j])
{
i++;
j++;
nexto[i]=j;
}
else
j=nexto[j];
}
}
void kmp(char w[],char t[])
{
int n=strlen(t);
int m=strlen(w);
getnext(w,next,m);
int i=0;
int j=0;
int ans=0;
while(i<n)
{
if(w[j]==t[i]&&j==m-1)
{
i++;
j++;
ans++;
}
else if(w[j]==t[i]&&j!=m-1)
{
i++;
j++;
}
else
{
j=next[j];
if(j==-1)
{
i++;
j++;
}
}
}
printf("%d\n",ans);
}
int main()
{
int l;
scanf("%d",&l);
while(l--)
{
memset(w,'\0',sizeof(w));
memset(t,'\0',sizeof(t));
scanf("%s%s",w,t);
kmp(w,t);
}
}