KMP的next函数有两种形式,一种是next[0]=-1的,另一种是next[0]=0的,这里采用了第二种。
分两个函数写成,1.求next;2.匹配。
求next和匹配的过程看上去有那么点点类似。上代码:
#include <iostream>
#include <iterator>
using namespace std;
// 求next函数
void build_next(char * s,int *next)
{
int i=0,j=-1;
int n = strlen(s);
next[0]=-1;
while(i<n)
{
if(j==-1 || s[i]==s[j])
{
++j;
++i;
next[i] = j;
}
else
{
j = next[j];
}
}
}
// kmp
int KMP(char s[],char t[],int m,int n, int *next)
{
build_next(t, next);
int i=-1;
int j=-1;
while( i<m && j<n)
{
if(j==-1 || s[i]==t[j])
{
++j;
++i;
}
else
{
j = next[j];
}
}
if(j<n)
return -1;
else
return i-n;
}
// 求sunday的数组
void getsun(char *s, int *sun)
{
memset(sun,0,sizeof(int)*256);
int n = strlen(s);
int i;
for(i=0;i<256;i++)
sun[i] = n+1;
for (i=0;i<n;i++)
{
sun[s[i]] = n-i;
}
}
// sunday算法
int sunday(char s[],char t[],int m,int n, int *sun)
{
int i=0,j=0;
while(i<m && j<n)
{
if(s[i] == t[j])
{
++j;
++i;
}
else
{
j = 0;
i = i - j + int(sun[s[i+n]]);
}
}
if(j<n)
return -1;
else
return i-j;
}
// 暴力搜索
int bf(char s[],char t[],int m,int n, int *sun)
{
int i=0,j=0;
while( i<m && j<n )
{
if (s[i] == t[j] )
{
++i;
++j;
}else
{
i = i-j+1;
j = 0;
}
}
if(j<n)
return -1;
else
return i-j;
}
int next1[20];
int main()
{
char s[] = "abacvhsvababca";
char t[] = "ababc";
int n=strlen(t);
int m=strlen(s);
// kmp
int index = KMP(s,t,m,n,next1);
cout<<"KMP:"<<endl<<index<<" "<<(s+index)<<endl;
copy(next1,next1+n,ostream_iterator<int>(cout," "));
cout<<endl;
// sunday
int *sun = new int[256];
getsun(t,sun);
cout<<endl<<"sunday:"<<endl;
//copy(sun,sun+256,ostream_iterator<int>(cout," "));
int ii = sunday(s,t,m,n,sun);
cout<<endl<<"sunday:"<<endl<<(s+ii)<<endl;
delete []sun;
cout<<"暴力搜索:"<<endl;
cout<<(s+bf(s,t,m,n,next1))<<endl;
return 0;
}