您的位置:首页 > 其它

Kmp算法; 建立在有限自动机理解基础上; 思想相当简单了;

2010-06-22 13:55 375 查看
#include <stdio.h>
#include <string.h>

/*********************************/
*   KMP算法
*   预处理时间:O(m), 运行时间O(n)
*   改进了状态机算法的预处理时间
*   依旧利用后缀最前前缀原理
*   理解有限自动机后理解此算法
/*********************************/

const int MAXN=10000;
char T[MAXN],P[MAXN];
int next[MAXN];

int m,n;

void computePrefixFunction()
{
m=strlen(P)-1;
next[1]=0;
int k=0;  // k比q延迟了2个身位
int q;
for(q=2;q<=m;++q)
{
while(k>0&&P[k+1]!=P[q])
{
k=next[k];
}
if(P[k+1]==P[q])
{
k=k+1;
}
next[q]=k;
}
}

void kmpMatcher()
{
n=strlen(T)-1;
m=strlen(P)-1;
computePrefixFunction();
int q=0; //q比i延迟了一个身位
int i;
for(i=1;i<=n;++i)
{
while(q>0&&P[q+1]!=T[i])
{
q=next[q];
}
if(P[q+1]==T[i]) //同时解决了q=0或者P[q+1]==T[i]两个问题
{
q=q+1;
}
if(q==m)
{
printf("匹配成功,位置:%d/n",i-m+1);
q=next[q];
}
}
}

int main()
{
T[0]=P[0]='z';
scanf("%s%s",T+1,P+1);
kmpMatcher();
return 0;
}


 

算法的思想是这样的, 如果当前已经匹配了一段, 结果匹配下一个字符的时候失败了,  那么应该将模式串向右移动多少来继续匹配呢?

 

next数组就是这个作用,什么作用呢?

 

假设文本串T与模式串P。

 

P[1...k]与T[]的某一段匹配了, 结果P[k+1]与T[]的下一个字符不相等.

 

这时候,怎么办?  可以在P[]里找一个P[1...k]的最长前缀,而且这个前缀是P[1...k]的一个后缀,  那么这个后缀一定也与T[]的后半段匹配, 假设这个后缀是P[1...s], 那么现在可以继续判断P[s+1]与T[]下一个字符是否相等, 重复这个过程 .如果相等, 那么i++, s++.

 

就是这么一回事, 基础一定是有限自动机.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  算法 include