字符串 II - KMP算法

字符串匹配问题。

一个长度为N的字符串T,模版是一个长度为M(M <= N)的字符串P,求出所有匹配点。


【朴素算法】 好像叫暴风(BF)算法。时间复杂度最坏是 O(M(N-1)) 。可以参考一下

void Simple(char *c, char *d) {
	int m = strlen(c), n = strlen(d);
	for(int i=0; i<=m-n; i++) {
		for(int j=0; j<n; j++) {
			if(c[i+j] != d[j]) break;
			if(j == n-1) printf("%d\n", i);
		}
	}
}

KMP算法(Kruth-Morris-Pratt)的效率很高,时间复杂度为 O(M+N),但是不易理解.

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;

#define IND 1 //这是下标从1开始 
#define NEXT 1 //输出next数组 

void GetFail(char *s, int *next) {              //失配函数 
	int m = strlen(s); 
	next[0] = next[1] = 0;                     //重要递推边界 
	for(int i=1; i<m; i++) {
		int j = next[i];                      //这是上个推好的next 
		while(j && s[i] != s[j]) j = next[j]; //顺着之前的 
		next[i+1] = s[i] == s[j] ? j+1 : 0;   //递推 
	}
}

void Find(char *A, char *T, int *next) {        //串、模版、next数组 
	int n = strlen(A), m = strlen(T);
	GetFail(T, next);
	int j = 0;                                 //模版T指针 
	for(int i=0; i<n; i++) {                   //文本串指针 
		while(j && T[j] != A[i]) j = next[j]; //失配 
		if(T[j] == A[i]) j ++;                //匹配长度+1 
		if(j == m) printf("%d\n", i-m+1+IND); //找到了 
	} 
}

char A[1000010], T[1000010];
int next[1000010], len;

int main() {
	scanf("%s%s", A, T);
	Find(A, T, next);
	len = strlen(T);
	if(!NEXT) return 0;
	for(int i=0; i<len; i++)
		printf("%d ", next[i+IND]);
	printf("\n");
	return 0;
}

KMP算法的精髓在于失配函数。自己匹配自己是算法核心。即如果有个模版是'abcdefghijkl',那KMP算法的优越性就无法体现(next数组都是0)。next数组可以理解为next[i]表示:如果匹配到i发现不对,应该接着匹配哪里(0就是从头匹配)。整个next数组构成了状态转移图,代码中的while循环就是顺着失配边不断转移,直到匹配。

接下来准备学习AC自动机.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值