您的位置:首页 > 其它

串的模式匹配 经典KMP算法

2011-09-17 18:08 267 查看
KMP算法是字符串匹配的经典算法,由于其O(m+n)的时间复杂度,至今仍被广泛应用。由D.E.Knuth与V.R.Pratt和J.H.Morris同时发现,因此人们称它为克努特——莫里斯——普拉操作(简称KMP算法)。KMP算法的关键是根据给定的模式串定义一个next函数。next函数包含了模式串本身局部匹配的信息。

其基本思想是:每当匹配过程中出现字符串比较不等时,不需回溯指针,而是利用已经得到的“部分匹配”结果将模式向右“滑动”尽可能远的一段距离,继续进行比较。

j | 1 2 3 4 5

模式 | a a a a b

next[j] | 0 1 2 3 4 带有缺陷的next

nextval[j] | 0 0 0 0 4 修正后的next

求出部分匹配数组Next是关键所在。

原来参考:http://www.ruanyifeng.com/blog/2013/05/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm.html

还有/article/5631720.html

具体实现代码如下:(参照《数据结构(C语言版)》串操作)

#include <iostream>
#include <fstream>
#include <string>
using namespace std;

ifstream fin("in.txt");

int nnext[100]={0};

void get_nnext(string t)	//求模式串t的nnext数组值
{
int i=0;
int j=-1;
nnext[0]=-1;
int tn = t.size();
while(i<tn-1)
{
if(j==-1 || t[i]==t[j])
{
i++; j++;
if(t[i]!=t[j]){
nnext[i]=j;
}else{
nnext[i]=nnext[j];
}
}else{
j = nnext[j];
}
}
return;
}

int Index_KMP(string s,string t)	//利用模式串的nnext函数求t在主串s中的位置的KMP算法。
{
int i = 0;
int j = 0;
int sn = s.size();
int tn = t.size();
while(i<sn && j<tn)
{
if(j==-1 || s[i]==t[j]){	 //若j==-1 表示已回溯到第一个仍不相等则下一个;若s[i]==t[j]表示当前字符匹配成功,下一个
i++;j++;
}else{
j=nnext[j];						//模式串向右移动
}
}
if (j>=tn)return i-tn;					//匹配成功
else return -1;							//匹配失败
}

int main()
{
string s,t;
fin>>s>>t;
get_nnext(t);
for(int i=0;i<t.size();i++)		//输出next数组
cout<<nnext[i]<<" ";
cout<<endl;
cout<<"KMP:"<<Index_KMP(s,t)<<endl;
system("PAUSE");
return 0;
}


输入文件in.txt:

BBCABCDABABCABCDABDE

ABCDABD
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: