KMP算法

前言

KMP算法是一种改进后的字符串匹配算法,即在一个字符串中定位另一个串的高效算法。通过辅助数组实现跳过扫描不必要的目标字符串,以达到优化效果。

视频

视频

思路

KMP有两个难点:
取最长公共前后缀.
和如何利用最长公共前后缀所反映的有效信息避免不必要的检测

最长公共前后缀匹配

字符串s1:ABABCA,求最长公共前后缀,我们只能找到最前面和最后面的两个A.
字符串s2:为ABABCAB,求最长公共前后缀,我们只需要在s1的基础上,检测那个字母是不是B即可.如果是B那么就在s1的基础上加1,如果不是那就为0

inline void GetNext()
{
	int i=0,j=-1,len=strlen(s);
	next[i]=j;
	while(i<len){
		while(j!=-1&&s[i]!=s[j]) j=next[j];
		next[++i]=++j;
	}
}

如何检测移动

s:ABABCA,如果s[0]与主串不匹配,那么j就为-1,通过下面的代码j++,使之为0,也就是向后移1位.
如果a[i]==s[j],就是继续匹配。如果不相等,那么next[j]号位移动到与主串当前位比较

int KmpIndex()
{
	GetNext();
	int i=0,j=0,lena=strlen(a),lens=strlen(s);
	while(i<lena&&j<lens){
		while(j!=-1&&a[i]!=s[j]) j=next[j];
		i++,j++;
	}
	if(j==lens) return i-lens;//模式串在主串中首次出现的位置
	else return -1;
}
int KmpCount()
{
	GetNext();
	int i=0,j=0,ans=0,lena=strlen(a),lens=strlen(s);
	while(i<lena){
		while(j!=-1&&a[i]!=s[j]) j=next[j];
		i++,j++;
		if(j==lens) ans++;
	}
	return ans;
}

模板题

Oulipo POJ - 3461

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int N=1e4+10;
const int M=1e6+10;
int t;
char a[M],s[N];//a主串
int next[N];
inline void GetNext()
{
	int i=0,j=-1,len=strlen(s);
	next[i]=j;
	while(i<len){
		while(j!=-1&&s[i]!=s[j]) j=next[j];
		next[++i]=++j;
	}
}
int KmpCount()
{
	GetNext();
	int i=0,j=0,ans=0,lena=strlen(a),lens=strlen(s);
	while(i<lena){
		while(j!=-1&&a[i]!=s[j]) j=next[j];
		i++,j++;
		if(j==lens) ans++;
	}
	return ans;
}
int main()
{
	scanf("%d",&t);
	while(t--){
		scanf("%s",s);
		scanf("%s",a);
		printf("%d\n",KmpCount());
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值