您的位置:首页 > 其它

字符串模式匹配——KMP算法

2012-11-17 23:33 197 查看
字符串的模式匹配问题即为在一串字符A当中寻找到一个子串使得子串与另一个字符串完全相同,把子串起始的下标输出即可。

对于这个问题,可以很直白的进行解决,也就是通常说的朴素的模式匹配,但是相对来说时间复杂度较高,为L(A)*L(B)。作为改进,KMP算法的时间复杂度只是线性的,所以更优。

KMP算法的本身代码实现并不复杂,思想框架也不复杂,但是里面的利用失败函数寻找next值方法却不好理解个人觉得。今晚费了两个多点才算是看明白并且给了实现。之前也有看过,大一学习数据结构的时候,但是那时候看了好多遍也没看明白,就放弃了。今晚终于啃下来了...

它的具体的思想和算法过程,想要学习的可以网上搜一下,应有竟有,这里只粘出代码,但是敢肯定的是,只看代码是肯定理解不了的...

代码实现:

#include<iostream>
using namespace std;

char target[1000]={'a','c','a','b','a','a','b','c','a','c','c','a','c','b','c'};
char pattern[100]={'a','b','a','a','b','c','a','c'};
int nextp[100];
int plength=8;
int tlength=15;

void failF()
{
int k=-1;int j=0;
nextp[0]=-1;
while(j<plength)
{
if(k==-1||pattern[k]==pattern[j])
{
k++;j++;
nextp[j]=k;
}
else
{
k=nextp[k];
}
}
}

void fastFind()
{
int k=0;
int j=0;
while(k<plength&&j<tlength)
{
if(k==-1||pattern[k]==target[j])
{
k++;
j++;
}
else
{
k=nextp[k];
}
}
if(k<plength)
{
cout<<"fail"<<endl;
}
else
{
cout<<j-k<<endl;
}
}

int main()
{
failF();
fastFind();
return 0;
}

上面这个代码只是找出第一个便终止了,要想找出所有的还需要改进。

改进的可以输出所有位置的代码:

#include<iostream>
using namespace std;

char target[1000]={'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a'};
char pattern[100]={'a','a','a'};
int nextp[100];
int plength=3;
int tlength=15;

void failF()
{
int k=-1;int j=0;
nextp[0]=-1;
while(j<plength+1)                                      //注意循环变量值,比原来大了1,也就是算出了第n位的next值
{
if(k==-1||pattern[k]==pattern[j])
{
k++;j++;
nextp[j]=k;
}
else
{
k=nextp[k];
}
}
for(int i=0;i<plength+1;i++)
cout<<nextp[i]<<"\t";
cout<<endl;
}

void fastFind()
{
int k=0;
int j=0;
int flag=true;                                  //增加了一个标志位,用来识别是否找到了符合条件的字串
while(j<tlength)
{
if(k==-1||pattern[k]==target[j])
{
k++;
j++;
}
else
{
k=nextp[k];
}

if(k==plength)                         //这里k为字符串长度的下一个值(n),而j也是子串的下一个位置,因为在前一个if语句里都执行了自加操作
{
flag=false;
cout<<j-k<<endl;
k=nextp[k];                        //这一句要与算出来第n位的next值连同起来看,是与前一个程序不同的核心
//j++;
}
}
if(flag)
{
cout<<"fail"<<endl;
}
}

int main()
{
failF();
fastFind();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: