KMP

模式匹配的KMP算法:

串的模式匹配的朴素算法是O(N^2)的,可以利用KMP(由D.E.Knuth,J.H.Morris,V.R.Pratt提出)算法改进至线性的算法。KMP算法与朴素算法的不同在于处理"失配"情况。不同于将指针完全回溯,KMP算法先根据已经部分匹配的信息,将匹配的指针跳过不必匹配的位置。匹配的算法如下:

#include<iostream>
#include<string>
using namespace std;
const int max=100;
int f[max];
int temp;
void fail(string&st)
{
int len=st.length();
f[0]=-1;
for(int j=1;j<len;++j)
{
int i=f[j-1];
while(st[j]!=st[i+1]&&i>=0)i=f[i];
if(st[j]==st[i+1])f[j]=i+1;
else f[j]=-1;
}
}
bool find(string&tent,string&path)
{
int t=0,p=0;
int lent=tent.length();
int lenp=path.length();
while(t<lent&&p<lenp)
{
if(tent[t]==path[p])
{
++t;
++p;
}
else if(p==0) ++t;
else p=f[p-1]+1;
}
if(p<lenp)return false;
else
{
temp=t-lenp;
return true;
}
}
int main()
{
string tent;
string path;
cout<<"请输入主串:";
cin>>tent;
cout<<endl;
cout<<"请输入模式串:";
cin>>path;
cout<<endl;
fail(path);
if(find(tent,path))
{
cout<<"匹配成功"<<endl;
cout<<"从主串的第"<<temp<<"个字符开始匹配"<<endl;
}
else cout<<"匹配失败"<<endl;
system("PAUSE");
return 0;
}

===================================================================

===================================================================
引用
void GetNext(char* t,int lt,int* next)
{
int i=0,j=-1;
next[0]=-1;
while(i<lt)
if(j<0 || t[i]==t[j])
{
i++; j++;
next[i]=j;
}
else
j=next[j];
}
引用
int KMP(char* s,char* t)
{
int next[10],i=0,j=0,lt,ls;
lt=strlen(t); ls=strlen(s);
GetNext(t,lt,next);
while(i<ls && j<lt)
if(j<0 || s[i]==t[j])
{
i++; j++;
}
else
j=next[j];
if(j<lt)
return -1;
else
return i-lt;
}
由于对主串的搜索不需要回溯,KMP算法的时间复杂度为O(N)。不过KMP算法仍有优化的余地,我们还可以根据已经掌握的信息,于"失配"时将模式串的指针尽量向左移。这一改进只需修改GetNext函数就可以了:
引用
void GetNext(char* t,int lt,int* next)
{
int i=0,j=-1;
next[0]=-1;
while(i<lt)
if(j<0 || t[i]==t[j])
{
i++; j++;
if(t[i]!=t[j])
next[i]=j;
else
next[i]=next[j];
}
else
j=next[j];
}
posted @ 2006-03-05 01:10  观我生,君子无咎  阅读(266)  评论(0)    收藏  举报