KMP的优化在于它省去了每次不必要比较的时间,从而提高查找的效率。主要用到next数组用来存放每次比较的位置。主要代码如下:
void getnext()
{
Next[0]=-1;
int i=0,j=-1;
while(i<lena)
{
if(j==-1||a[i]==a[j])
{
i++;
j++;
if(a[i]==a[j])
Next[i]=Next[j];
else
Next[i]=j;
}
else
j=Next[j];
}
}
int KMP()
{
int i=0,j=0,ans=0;
while(i<lena&&j<lenb)
{
if(i==-1||a[i]==b[j])
{
i++;
j++;
}
else
{
i=Next[i];
}
if(i==lena)
{
ans++;
i=Next[i];
}
}
return ans;
}
我们在应用时看题i型而变,修改next函数的条件和参数。例如杭电上的http://acm.hdu.edu.cn/webcontest/contest_showproblem.php?pid=1000&ojid=0&cid=12677&hide=0
大致意思就是给你一个主串和模式串看看模式串出现在主串中的位置。
我们l利用kmp算法,将传入的变量改为两个整形数组,这个时候就不用在next函数中统计其出现的次数,返回的值应该是匹配成功后第一个字母的位置。具体代码如下:
#include<iostream>
#include<stdio.h>
using namespace std;
#define MAXN 1000000
#define MAXM 10000
int a[MAXN],b[MAXM];
int next[MAXN];
int n,m;
void getnext(int p[],int next[])//next数组用来储存每次比较的i和j位置
{
int j,k;
next[0]=-1;
j=0;
k=-1;
while(j<m-1)
{
if(k==-1||p[j]==p[k])
{
j++;
k++;
next[j]=k;
}
else
k=next[k];
}
}
int kmp(int s[],int p[])
{
int j,i;
i=0;
j=0;
getnext(p,next);
while(i<n)
{
if(j==-1||s[i]==p[j])
{
i++;
j++;
}
else
{
j=next[j];
}
if(j==m)
return i-m+1;//返回到匹配成功后第一个字母的位置
}
return -1;
}
int main()
{
int t,j,i;
scanf("%d",&t);
while(t--)
{
scanf("%d %d",&n,&m);
for(i=0;i<n;i++)
scanf("%d",&a[i]);
for(i=0;i<m;i++)
scanf("%d",&b[i]);
printf("%d\n",kmp(a,b));
}
return 0;
}
注意:再提交时next是关键字,一般别用next直接开数组。