KMP算法

懒,随便写点敷衍下吧。


KMP中的灵魂,next[]数组。next[i]记录的是一个部分匹配,模式串t,假设是tomatoabc

后缀toabc中正好有开头的“to”,开与主串s匹配时,假设到toabc的b失败了,(可以认为s是。。。tomatoacb。。。),我们不必返回,直接在tomatoacb这里继续匹配。

next[i]记录的,正是当前字符之前,与开头匹配的串的长度。规定,next[0]=-1  next[1]=0

#include "stdafx.h"
#include "iostream"
#include "string"

#define len 1024

using namespace std;

void GetNext(string t,int next[]){
	int j=0,k=-1;
	next[0]=-1;
	while(j<t.length()){
		if(k==-1 || t[j]==t[k]){
			j++;
			k++;
                        next[j]=k;
		}
		else
			k=next[k];
	}
}

int MyKMP(string s,string t){
	int next[len],i=0,j=0;
	GetNext(t,next);
	while(i<s.length() && j<(int)t.length()){
		if(j==-1 || s[i]==t[j]){
			i++;
			j++;
		}
		else
			j=next[j];
	}
	if(j>=t.length())
		return (i-t.length());
	else
		return  -1;//not found
}

int _tmain(int argc, _TCHAR* argv[])
{
	string s,t;
	cin>>s>>t;
	cout<<MyKMP(s,t)<<endl;

	return 0;
}

这个时候GetNext函数有个缺陷,比如s:aaabaaaab        t:aaaab

推导过程略,直接结论:

void GetNext(string t,int next[]){
	int j=0,k=-1;
	next[0]=-1;
	while(j<t.length()){
		if(k==-1 || t[j]==t[k]){
			j++;
			k++;
			if(t[j]!=t[k])
				next[j]=k;
			else
				next[j]=next[k];
		}
		else
			k=next[k];
	}
}


你可能感兴趣的:(KMP算法)