KMP
KMP算法是一种利用前缀函数快速得出对应字符串是否匹配的算法.
所以我们在打KMP之前需要先会求前缀函数.
解释一下前缀函数是什么以及KMP的大致过程.
首先前缀函数存储的是某个字符串的前缀中,最长的既是前缀又是后缀的串长.
如何求前缀函数值呢?
直接暴力匹配,一个一个位置截出前缀串,再在前缀串中一位一位匹配.
效率奇低,O(n^3).
加上部分优化,观察可知我们每一次都只有可能在前一个前缀的前缀函数值上加1,所以没有必要从头开始匹配.
改为每一次从上一个的前缀函数表示的前缀的末位处开始匹配即可,但是在失配之后还是要从前一个前缀的border一位位重新开始匹配,极限时间复杂度O(n^2)
再加上一步优化,因为我们已知上一个前缀的前缀函数末位若无法与当前位匹配,我们只能找到最大的比当前border小的border尝试匹配.
那么最大的比当前试配的border值小的border如何得到?就是我们当前试配的border的border.
如此就得到了前缀函数的求解方法.
求前缀函数的模板:
#include<bits/stdc++.h>
using namespace std;
const int N=4e5+520;
int pi[N],len;
char s[N];
void get_pre()
{//得到一个串所有点的前缀函数值
for(int i=1;i<len;++i)
{
int j=pi[i-1];
while((s[i]^s[j])&&j)j=pi[j-1];
if(s[i]^s[j])pi[i]=j;
else pi[i]=j+1;
}
}
void init()
{
while(cin>>s)
{//输入的时候必须是首位有意义
len=strlen(s);
get_pre();
for(int i=0;i<len;++i)
printf("%d ",pi[i]);
}
}
int main()
{
init();
return 0;
}
板子题题目链接.
这里不放正解了,有点太简单,占博文空间了.
思路是在咱们求出前缀函数之后再以前缀函数值进行跳转即可.
模板品种update:
void get_pre()
{
for(int i=1,j=0;i<len;++i)
{//这里让长度为j的border的pi值对应j-1位,每次转移的时候直接用j=pi[j]即可.
while(j&&(s[j]^s[i]))j=pi[j];
j+=(s[i]==s[j]);
pi[i+1]=j;
}
}
因为这道题更新了一版模板.
https://www.cnblogs.com/shining-like-stars