KMP原理
原理部分参考博文:博客链接
参考视频:视频链接
力推视频,讲的易懂。
代码实现
#include <iostream>
#include<bits/stdc++.h>
#define ll long long
#define MaxN 1000+5
using namespace std;
/*
**KMP算法实现
*/
int prefix[MaxN] = {0};//前缀表
void getPrefix(string s)
{
prefix[0] = 0;
int len = 0;//记录前缀长度
int i = 1, n = s.size();//记录位置
while(i < n){
if(s[i] == s[len]){
len++;
prefix[i] = len;
i++;
}
else{
len = prefix[len-1];
prefix[i] = len;
i++;
}
}
}
void Swap(int n)
{
for(int i = n-1; i > 0; i--)
{
prefix[i] = prefix[i-1];
}
prefix[0] = -1;//这里把第一位标记为-1为了便于底下查找
}
void KMP_Search(string s, string str)
{
//s是字符串文本,str是查找的内容
//i执行s, j指向str
int i = 0, j = 0;
while(i < s.size())
{
if(j == str.size()-1 && s[i] == str[j]){
//找到出现的位置
cout << "出现在: " << i-j << endl;
j = prefix[j];//找下一次出现的位置
}
if(s[i] == str[j])
{
i++;
j++;
}
else
{
j = prefix[j];
if(j == -1)
{
//从头开始找
i++;
j++;
}
}
}
}
int main()
{
string str, s;
//getline(cin, s);//文本字符串
//getline(cin, str);//查找的字符串
str = "ABABCABAA";
s = "ABABABCABAABABABCABAAXXX";
getPrefix(str);
Swap(str.size());
KMP_Search(s, str);
return 0;
}
总结
KMP就是用一个Prefix数组记录前缀长度,然后每次窗口滑动的时候,不是单纯的一步一步的移动,直接移动prefix[i]对应的长度,保证前i-1位已经配对了,从第 i 位开始往后判断