KMP算法

菜鸟KMP算法钻研之路,花了一下午,QAQ,自己理解写下的。

KMP算法 主要被分解为以下两个函数:

1,GetNext(string p,int next[]),通过这个函数获得关于p的next数组。

关于next数组:1,大小为p.getlength()+1,因为下标从1到p.getlength(),next[0]没用到,就赋值其为next[0]=-1;

 2,next[i]的值:返回p[0]到p[i-1]子串中最大公共串的大小。(公共串:emmmQAQ不会定义,举个例子,假设子串为ABABA,那最大的公共串为ABA(因为前三 ABA后三ABA),此时next[i]=3).

 3,如何求next[i+1],利用next[i]求next[i+1],初始的next[1]=0.下面举个例子:

比如有一串为"abaaabba"

子串分解 "a" ,此时i=1,next[i]=0,j=next[i]=0;

"ab",p[j]='a',因为p[j]!=p[i],那么此时next[i+1]=0(next[2]求得),i++,j=next[i]=0,此情况的代码如图

                                              

if(j==0&&p[j]!=p[i]){
			next[i+1]=0;
			i++;
			j=next[i];	
		}

"aba",因为p[j]=‘a’,p[i]='a'=p[j],那么此时next[i+1]为next[i]+1(next[3]求得)即j+1=1;公共串为'a',i++,j=next[i] 此情况的代码如图

   

	if(p[j]==p[i]){
			next[i+1]=j+1;
			i++;
			j=next[i];
			//状况一 
		}

                                       


"abaa":因为p[j]='b'!=p[i]='a',不行要退一步,j=next[j],得到p[j]=p[0]='a',p[j]=p[i]可以了,那么next[i+1]=j+1(next[4]求得),然后i++,j回来j=next[i]此情                                                         况的到代码如图

if(p[j]==p[i]){
			next[i+1]=j+1;
			i++;
			j=next[i];

		}
		else
			j=next[j];//先直接进入else 

然后

if(p[j]==p[i]){
			next[i+1]=j+1;
			i++;
			j=next[i];

		}//接着再进入if 
		else
			j=next[j]; 


"abaaa"  p[j]=p[1]='b'!=p[i],回去j=next[j]=next[1]=0.然而,p[j]=p[0]='a'!=p[i]='a',咋整呀,也回不去了,这时候又进入这种状况


  1.  if(j==0&&p[j]!=p[i]){  
  2.             next[i+1]=0;  
  3.             i++;  
  4.             j=next[i];    
  5.         }  

····························直接next[i+1]=0,继续i++,j回来j=next[i]。

"abaaab"

"abaaabb"

"abaaabba".........以此类推


完整代码如下

void Getnext(string p,int next[]){ 
	int i=1;
	next[0]=-1;//下标从1开始,所以next[0]=-1; 
	next[1]=0;//固定的 
	int j=next[i];
	while(i<p.length()){ 
		if(j==0&&p[j]!=p[i]){
			next[i+1]=0;
			i++;
			j=next[i];	
		}
		else
		if(p[j]==p[i]){
			next[i+1]=j+1;
			i++;
			j=next[i];

		}
		else
			j=next[j]; 
	}
} 



2,GetIndex(string mainstr,string p,int index,int next[])

本菜鸟当初卡这卡了好久啊QAQ  最后辛苦改bug才知道自己之前没有认真把握好i指针的移动。

移动处之一,两串串单个字符匹配成功i++啦;

移动处之二,两串串单个字符匹配不成功,这时候i不要先移动,让模式串的指针j移动,j=next[j]。

移动呀 匹配不成功 那就继续移动呀 哎呀卧槽j=0移动不了了咋整,还是匹配不成功啊QAQ,这时候就要开始移动i了没错开始移动i了

然后     循环跳出的条件当然是 要么主串遍历完了,或者模式串遍历完了

当模式串遍历完了  跳出循环 返回INDEX的值

否则 返回-1表示模式串在主串不存在!


int Getindex(string mainstr,string p,int next[],int pos){
		int i=pos,j=0;
		while(i<mainstr.length()&&j<p.length()){
			if(mainstr[i]==p[j]){
				++i;++j;
			}
			else{
				if(j==0)
					i++;
				else
				j=next[j];
			}
		}
		if(j==p.length())	return i-j+1;
		else              return -1;

	
}

好了 完整代码加上测试main函数

#include<iostream>
#include<string>
using namespace std;
void Getnext(string p,int next[]){ 
	int i=1;
	next[0]=-1;//下标从1开始,所以next[0]=-1; 
	next[1]=0;//固定的 
	int j=next[i];
	while(i<p.length()){ 
		if(j==0&&p[j]!=p[i]){
			next[i+1]=0;
			i++;
			j=next[i];	
		}
		else
		if(p[j]==p[i]){
			next[i+1]=j+1;
			i++;
			j=next[i];

		}
		else
			j=next[j]; 
	}
} 
int Getindex(string mainstr,string p,int next[],int pos){
		int i=pos,j=0;
		while(i<mainstr.length()&&j<p.length()){
			if(mainstr[i]==p[j]){
				++i;++j;
			}
			else{
				if(j==0)
					i++;
				else
				j=next[j];
			}
		}
		if(j==p.length())	return i-j+1;
		else              return -1;

	
}
int main(){
	string str;
	string mainstr;
	cin>>mainstr;
	cin>>str;
	//测试 
	int *next=new int[str.length()+1];
	Getnext(str,next);
	for(int i=1;i<str.length()+1;i++)
		cout<<next[i]<<" ";
	cout<<endl<<Getindex(mainstr,str,next,0); 
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值