基础数据结构第六期 KMP算法


前言

KMP算法在解决字符串匹配问题时十分重要,本文将为大家介绍KMP算法

一、如何字符串匹配?

(1) 暴力做法:该方法是我们常常想到的,虽然该方法好理解,但是该方法有较高的时间复杂度。

模板:

基础数据结构第六期 KMP算法_第1张图片

(2)KMP算法:

KMP算法的核心是求解next[]数组,即我们在匹配失败后j应该跳到的位置,下面给出next数组的求法    模板:

for(int i = 2,j = 0;i <= n;i ++){ 
		while(j && p[i] != p[j+1]) j = ne[j];
		if(p[i] == p[j+1]) j++;
		ne[i] = j;
	}//匹配自己

KMP算法的流程如下:

假设现在文本串S匹配到i位置,模式串P匹配到j位置,

如果j = -1,或者当前字符匹配成功(即S[i] == P[j]),令i++,j++,继续匹配下一个字符;

如果j != -1,且当前字符匹配失败(即S[i] != P[j]),则令i不变,j = next[j],即模式串P相对于文本串S向右移动了j - next [j]位。当匹配失败时,模式串向右移动的位数为:j - next[j],且此值大于等于1。

next数组各值的含义:代表当前字符之前的字符串中,有多大长度的相同前缀后缀。例如next [j] = k,代表j之前的字符串中有最大长度为k 的相同前缀后缀,即在某个字符失配时,该字符对应的next值会告诉下一步匹配中,模式串应该跳到哪个位置(跳到next[j]的位置)。如果next[j]等于0或-1,则跳到模式串的开头字符,若next[j] = k 且 k > 0,代表下次匹配跳到j之前的某个字符,而不是跳到开头,且具体回溯跳过了k个字符。
模板:

for(int i = 1,j=0;i <=m;i ++){
	    while(j && s[i] != p[j+1]) j = ne[j];
		if(s[i] == p[j+1]) j++;
		if(j==n)
		{
			//cout << i-n << " ";
		    //j = ne[j];
		}//匹配成功
	}

二、典型例题

1.例题

基础数据结构第六期 KMP算法_第2张图片

2.AC代码

#include
using namespace std;

const int N = 1e5+8;
int n,m,ne[N];
string s,p;

int main()
{
   	cin >> n >> p >> m >> s;
	p = ' '+p;
	s = ' '+s;
	for(int i = 2,j = 0;i <= n;i ++){ 
		while(j && p[i] != p[j+1]) j = ne[j];
		if(p[i] == p[j+1]) j++;
		ne[i] = j;
	}//匹配自己
	for(int i = 1,j=0;i <=m;i ++){
	    while(j && s[i] != p[j+1]) j = ne[j];
		if(s[i] == p[j+1]) j++;
		if(j==n)
		{
			cout << i-n << " ";
		    j = ne[j];
		}//匹配成功
	}
	return 0;
}

总结

以上就是我对KMP算法的基本理解感谢大家的观看,谢谢大家!!!

你可能感兴趣的:(算法)