串模式匹配之------KMP

       在使用BF算法进行模式匹配时,效率较低,时间复杂度到过了o((n+m)m)后来出现的KMP算法相对于BF算法在效率上有了较大的提高o(m+n)。BF算法效率低是因为每次它的模式串指针都要回溯到开头的位置。如果避免每次都回到开头,那么效率就会提高,这就是KMP的思想之一。

如有 目标串:T(t0t1t2t3.....tk......tm-1)

        模式串:   s(s0s1s2s3...sk.....sk-1)

若模式和目标串在k处出现了不同,则前可以把T改成(s0s1s2s3...sk-1,tk,tk+1.....tm-1)由此看来,每一次比较就没必要从头开始了,在模式串中存在着某种对应关系来确定指针的回溯位置。这种关系我们用“失配函数”来表示。失配函数用一个数组next[j]表示(j模式串的字符个数)next[0]规定为-1。其它的可以用下面的方法确定。

  把j当作失配函数的定义域 其取值范围为 0=<j<s.size();

 k为失配函数的值域,其取值为在0=<k<j中使得p0p1..pk=pk-jpk-j+1...pj成立的K的最大值。

如:s="caatcat"

当j=1时 k=0, s[0]!=s[1] next[1]=-1;

当j=2,k=0,1,  s0s1!=s1s2;s0!=s2,next[2]=-1;

j=3,k=0,1,2;   s0!=s3,s0s1!=s2s3,s0s1s2!=s1s2s3;s[3]=-1;

j=4,k=0,1,2,3 s0=s4,s0s1!=s3s4,s0s1s2!=s2s3s4;s0s1s2s2!=s1s2s3s4;next[4]=0;

j=5,k=0,1,2,3,4 ,s0s1=s4s5;next[5]=1;

j=6,k=0,1,2,3,4,5,next[6]=0;

然后是比较过程:

设T是目标串,S是模式串,并设指针i,j分别指向T,S要比较的字符,开始令i,j都等于0,比较t(i)和S(j)如果相等,则i和j都加1,如果不等,则j回到next[j]。i不变。再用t(i)和s(next[j])比较,如果相等,各回1,如果next[j]=-1则从T(i+1)和t0开始比较。

具体实现如下:

# include <iostream>
# include <string>
using namespace std;
//失配函数的实现
void nextval(string s,int next[])
{
    int j=0,k=-1;
	next[0]=-1;
	while(j<s.size())
	{
       if(k==-1||s[j]==s[k])
	   {
		   j++;
		   k++;
		   if(s[j]!=s[k])
			   next[j]=k;
		   else
			   next[j]=next[k];
	   }
	   else
		   k=next[k];
	}

}
int find(string s,string t)
{
	int next[100],i=0,j=0;
      nextval(t,next);
	  int lens=s.size();
	  int lent=t.size();
	  while(i<lens&&j<lent)
	  {   
		  
		  
		  if(j==-1||s[i]==t[j])
		  {
			  i++;
			  j++;
			  
			 
		  }
		  else
		  {
			  j=next[j];
			 
		  }
	  }
	
	  if(j>=t.size())
	  {
		 
		  return (i-t.size());
	  }
	  else
		  return -1;
}
int main()
{   
	string s("abcabaa");
    string t("abcaabbabcabaacbacba");
	int x=find(t,s);
	if(x==-1)
		cout<<"查找失败"<<endl;
	else
		cout<<"从第"<<x<<"位开始匹配成功"<<endl;
			return 0;

}


 


 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值