KMP

实现

现在有两个串a,b:

AAABAAABAAAC

AAAC

要从a中找到b,最简单的方法显然是暴力,那么时间复杂度会非常高,高达O(len1×len2)O(len1\times len2)

有没有更快的方法?KMP大显身手!

KMP的思想基于最长公共前后缀。

设字符串T=“aabaaf”,我们求一下T的前缀表(用一个数组名为nxt的数组表示)。

  1. 第一个子串是t0=“a”,易知该子串没有前缀也没有后缀,故nxt[0]=0
  2. 第二个子串是t1=“aa”,该子串的前缀为"a",后缀也为"a",故nxt[1]=1
  3. 第三个子串是t2=“aab”,该子串的后缀中一定会有"b",前缀中一定不含有"b",则其没有相等的前后缀,故nxt[2]=0
  4. 第四个子串是t3=“aaba”,该子串的最大相等前后缀为"a",长度为1,故nxt[3]=1
  5. 第五个子串是t4=“aabaa”,该子串的最大相等前后缀为"aa",长度为2,故nxt[4]=2
  6. 第六个子串是t5=“aabaaf”,该子串的后缀中一定会有"f",前缀中一定不含有"f",则其没有相等的前后缀,故nxt[5]=0

所以,这个nxt实际上就是KMP在失配时跳到的位置

板子

get_nxt:

void get_nxt(string x){
	int j=0,k=-1,len=x.size(); 
	nxt[0]=-1;
	while(j<len){
		if(k==-1||x[j]==x[k]){
			j++,k++;
			nxt[j]=k;
			bro[j-1]=k;
		}
		else{
			k=nxt[k];
		}
	}
}

kmp

void KMP(string s,string t){
	int j=0,i=0,slen=s.size(),tlen=t.size(); 
	get_nxt(t);
	while(i<slen){
		if(j==-1||s[i]==t[j]){
			j++,i++;
		}
		else{
			j=nxt[j];
		}
		if(j==tlen){
			cout<<i-tlen+1<<endl;
			j=nxt[j];
		}
	}
}

时间复杂度O(len)O(len)

posted @   KK_SpongeBob  阅读(3)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 百万级群聊的设计实践
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 全网最简单!3分钟用满血DeepSeek R1开发一款AI智能客服,零代码轻松接入微信、公众号、小程
· .NET 10 首个预览版发布,跨平台开发与性能全面提升
· 《HelloGitHub》第 107 期
点击右上角即可分享
微信分享提示