目录
KMP算法介绍:
KMP(Knuth-Morris-Pratt)算法是一种字符串匹配算法,用于在一个文本字符串中搜索一个模式字符串的出现位置。它的名字来源于发明者的姓氏。
KMP算法的主要思想是利用已经匹配过的信息来避免不必要的比较,从而提高匹配的效率。它通过构建一个部分匹配表(Partial Match Table)来实现这一点。
部分匹配表是模式字符串自身的一种自我匹配表,它记录了模式字符串中每个前缀子串的最长相同前缀后缀长度。这些信息告诉算法在匹配过程中,当出现不匹配的字符时,可以跳过一些比较操作,直接将模式字符串向右移动到一个新的位置,从而减少比较的次数。
KMP算法的详细步骤:
1. 首先,构建模式字符串的部分匹配表。遍历模式字符串,对于每个位置i,计算模式字符串的前缀子串[0, i]的最长相同前缀后缀长度,并将这个长度记录在部分匹配表中的位置i上。
2. 在匹配过程中,维护两个指针:一个指向文本字符串中当前要匹配的字符,另一个指向模式字符串中当前要匹配的字符。
3. 开始匹配过程。将两个指针初始化为0,然后从左到右遍历文本字符串中的字符。
4. 如果当前字符匹配成功,将两个指针都向右移动一位,继续比较下一个字符。
5. 如果当前字符不匹配,根据部分匹配表中的信息,将模式字符串向右移动一定的距离,然后继续比较当前字符和模式字符串中对应位置的字符。
- 如果部分匹配表中对应位置的值为0,表示无法再向右移动,将模式字符串的指针移动到下一个位置,继续匹配。
- 如果部分匹配表中对应位置的值大于0,表示可以向右移动一定的距离。
6. 重复步骤4和步骤5,直到匹配成功或者遍历完整个文本字符串。
kmp算法总结:
KMP算法的核心是在匹配过程中,根据部分匹配表的信息来确定模式字符串的移动距离,从而减少不必要的比较操作。这种优化使得KMP算法的时间复杂度为O(n+m),其中n是文本字符串的长度,m是模式字符串的长度。相比于朴素的字符串匹配算法,KMP算法具有更高的效率。
kmp模板代码:
#include<iostream>
#include<cstring>
using namespace std;
const int N=1e5+6; // 模式字符串的最大长度
const int M=1e6+6; // 文本字符串的最大长度
int n,m; // 模式字符串和文本字符串的长度
char s[M],p[N]; // 用于存储文本字符串和模式字符串的数组
int ne[N]; // 用于存储模式字符串的next数组
int main(){
cin>>n>>p+1>>m>>s+1; // 输入模式字符串和文本字符串的长度,以及模式字符串和文本字符串的内容
// 预处理步骤:构建模式字符串的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;
}
// 在文本字符串中搜索模式字符串的出现位置
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){
printf("%d ",i-n); // 打印每个模式出现在文本中的起始位置
j=ne[j];
}
}
return 0;
}