[学习笔记]kmp学习笔记

kmp学习笔记

问题:
给定两个字符串,将两个字符串进行匹配

原理:
n^2暴力?那还要这个算法有啥用……
先看一下简便的匹配方法:

这时候我们发现在D位置是失配,如果按照暴力方式的话我们要从位置A开始继续匹配


但是由于前面一定是匹配上的,我们就可以从C开始。

对于这种失配后跳到的节点我们把它叫做当前节点的失配。(个人的理解是当前字符的前一段字符串有多长与整个字符串的前缀相等)
举个栗子:
abcdab c
注意加红的c,我们发现,他前面的字符串'ab'与整个字符串的前缀'ab'相等,且长度为二,那么c的失配就是2。(因为如果匹配到c,那么带匹配的字符串匹当前配到的字符的前两位一定是'ab'要不然已经跳回到前面去了,所以下次匹配是只要从2号开始就行了)

实现:
因为每个字符的失配取决于它的前一个节点,可以递推。时间复杂度:O(n)

代码:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
using namespace std;

const int max_s = 100001;

char s[max_s], ori[max_s];
int fail[max_s];

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

inline void kmp()
{
	int lens=strlen(ori),len=strlen(s);
	int j=0;
	
	for(int i=0; i<lens; ++i)
	{
		while(j!=-1 && s[j]!=ori[i]) j=fail[j];
		j++;
		if(j==len) printf("get\n"),j=fail[j];
	}
}

int main()
{
	scanf("%s%s", ori, s);
	make_fail();
	kmp();
	for(int i=0; i<strlen(s); ++i)
	  printf("%d ",fail[i]);
	return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值