kmp与exkmp算法

kmp 

 

 

#include<bits/stdc++.h>
using namespace std;
/*
朴素kmp算法,可简化
const int N=1e6;
const int M=1e6;
int n,m;//m是小的,n是大的
int nxt[M+1],f[N+1];
char s[N+2],p[M+2];
void kmp(){
	int j=0;
	nxt[1]=0;
	for(int i=2;i<=m;i++){//计算next数组,即寻找回溯位置
		while(j>0&&p[i]!=p[j+1]){
			j=nxt[j];
		}
		if(p[j+1]==p[i])
			++j;
		nxt[i]=j;
	}
	j=0;
	for(int i=1;i<=n;i++){
		while((j>0&&s[i]!=p[j+1])||j==m){//匹配失败或者到上限就回溯
			j=nxt[j];
		}
		if(p[j+1]==s[i])
			++j;
		f[i]=j;
	}
}
*/

或者把两个字符串拼接,小的在前大的在后,中间用其他字符隔断

const int N=1e6;
const int M=1e6;
int n,m;//m是小的,n是大的
int nxt[N+M+2];
char s[N+2],p[N+M+2];
void kmp(){
	n=strlen(s+1);
	m=strlen(p+1);
	p[m+1]='#';
	for(int i=m+2,j=1;i<=n+m+1;j++,i++)
	{
		p[i]=s[j];
	}
	int j=0;
	nxt[1]=0;
	for(int i=2;i<=n+m+1;i++){
		while(j&&p[i]!=p[j+1])
		{
			j=nxt[j];
		}
		if(p[i]==p[j+1])
			j++;
		nxt[i]=j;
	}
}
int main(){
	scanf("%s%s",s+1,p+1);
}

例题1

答案就是n-next[n] 

例题2

做法就是将字符串反转之后拼接,中间用#隔断,输出后段字符串里面最大的next就行 

接下来是exkmp 

 

 

 

 

const int N=1e6;
int n,z[N+1];//记录拓展kmp结果
char s[N+1];//字符串
void exkmp(){
	int L=1,R=0;//维护l到R这个区间,L到R内元素与1到L-R+1中元素相等
	z[1]=0;//初始化
	for(int i=2;i<=n;i++){
		if(i>R)
			z[i]=0;//i不在区间内,之后要暴力匹配
		else{//i在区间内,不用暴力匹配
			int k=i-L+1;//即i元素在1到L-R+1中的相对位置
			z[i]=min(z[k],R-i+1);
		}
		while(i+z[i]<=n&&s[1+z[i]]==s[i+z[i]])//在有效范围内进行匹配
			++z[i];
		if(i+z[i]-1>R)
			L=i,R=i+z[i]-1;//更新RL区间
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值