字符串匹配搜索最著名的当属KMP算法,今天花了一番功夫研究了一下该算法。
算法的优点是时间复杂度和字符串的长度成线性关系,对于目标字符串T[n]和模式字符串P[m],算法需要的时间复杂度为O(m)的预处理和O(n)的匹配。具体的算法参见算法导论。
利用KMP算法完成类似于strstr()的功能,打印一个字符串中所有以子串开头的组合。
#include
<
iostream
>
#include < cstring >
using namespace std;
void Pre_Process( const char * P, int * pi)
... {
int m=strlen(P);
int i,j=0;
pi[0]=0;
for(i=1;i<m;++i)
...{
while(j>0&&(P[j]!=P[i]))
j=pi[j-1];
if(P[j]==P[i])
++j;
pi[i]=j;
}
}
void KMPstrstr( const char * T, const char * P)
... {
int n=strlen(T);
int m=strlen(P);
int* pi=new int[m];
Pre_Process(P,pi);
int q=0,i;
for(i=0;i<n;++i)
...{
while(q>0&&(P[q]!=T[i]))
q=pi[q-1];
if(P[q]==T[i])
++q;
if(q==m)
...{
for(int i0=i-m+1;i0<n;++i0)
cout<<T[i0]<<" "<<ends;
cout<<endl;
q=pi[q-1];
}
}
delete[] pi;
}
int main()
... {
char T[]="aaababaabaababaab";
char P[]="aabab";
KMPstrstr(T,P);
return 0;
}
#include < cstring >
using namespace std;
void Pre_Process( const char * P, int * pi)
... {
int m=strlen(P);
int i,j=0;
pi[0]=0;
for(i=1;i<m;++i)
...{
while(j>0&&(P[j]!=P[i]))
j=pi[j-1];
if(P[j]==P[i])
++j;
pi[i]=j;
}
}
void KMPstrstr( const char * T, const char * P)
... {
int n=strlen(T);
int m=strlen(P);
int* pi=new int[m];
Pre_Process(P,pi);
int q=0,i;
for(i=0;i<n;++i)
...{
while(q>0&&(P[q]!=T[i]))
q=pi[q-1];
if(P[q]==T[i])
++q;
if(q==m)
...{
for(int i0=i-m+1;i0<n;++i0)
cout<<T[i0]<<" "<<ends;
cout<<endl;
q=pi[q-1];
}
}
delete[] pi;
}
int main()
... {
char T[]="aaababaabaababaab";
char P[]="aabab";
KMPstrstr(T,P);
return 0;
}
程序输出结果:
aababaabaababaab
aababaab