KMP匹配

KMP匹配

定义nextt[i] 为 模式串b中的第i个数字的真前后缀最大公共子串长度

**eg: ababac 下标从1开始,nextt[1] = 0, next[2] = 0, next[3] = 1(因为b[1]和b[3]是此时相同前后缀的最大长度)......依次类推 **

至于kmp的原理简单来说就是在朴素算法的基础上在匹配a[i] 和 b[j]时,如果不等,每次由模式串整体向后移一位,变成了只动模式串,将j变成了nextt[j],然后再去匹配a[i] 和 b[j],这样可以极大的提升匹配效率,因为显然j到nextt[j]中间这段是无法匹配成功的。 很多博客写得更加清楚可以参考一下。

简单点理解kmp就是,首先令文本串a不动,接着不断地去匹配a[i] 与 b[j],通过j = nextt[j] 的操作我们删去了中间必定失配的过程。

代码示例:

//#pragma comment(linker,   "/STACK:10240000000000,10240000000000")
//#pragma GCC optimize(2)

#include <bits/stdc++.h>

#define For(i,a,b) for (int i=(a);i<=(b);++i)
#define Fod(i,b,a) for (int i=(b);i>=(a);--i)
#define mls multiset
#define lb lower_bound
#define ub upper_bound
#define pb push_back
#define pob pop_back
#define itt iterator
#define lowbit(x) x & (-x)
#define clr(x) memset(x, 0, sizeof(x));

typedef long long ll;
typedef unsigned long long ull;
		
using namespace std;
const int MAXN = 0x7fffffff;
const int MOD = 1000000007;
const ll MOD1 = 212370440130137957ll;

const int N = 1e6 + 5;

int nextt[N];

char a[N], b[N];

int alen, blen;

void getnext(int len) // 求nextt数组 模式串与自己匹配
{
	for(int i = 2, j = 0; i <= len; i++) //j为
	{
		while(j && b[j + 1] != b[i]) j = nextt[j]; //如果无法匹配,最大的子前后缀公共字符串长度一定为nextt[j]。
		if(b[j + 1] == b[i]) j++;//前后缀匹配成功, 长度+1
		nextt[i] = j;
	}
}

void kmp(int alen, int blen)  //文本串与模式串匹配
{
	for(int i = 1, j = 0; i <= alen; i++)
	{
		while(j && b[j + 1] != a[i]) j = nextt[j];
		if(b[j + 1] == a[i]) j++;
		if(j == blen)
		{
			cout << i - blen + 1 << endl;
			j = nextt[j];
		}
	}
}

int main ()
{	
	ios::sync_with_stdio(false);
	cin.tie(0);

	cin >> a + 1 >> b + 1;

	alen = strlen(a + 1);
	blen = strlen(b + 1);

	getnext(blen);
	kmp(alen, blen);

	For(i, 1, blen) cout << nextt[i] << " ";
	return 0;
}	

上一篇:java笔记【5.KMP算法】


下一篇:KMP算法