标签:ext mat 遇到 class 朴素 return ++ ret 自身
KMP算法是一种用于字符串匹配的算法,网上关于kmp的介绍很多,也十分复杂,(其实我也没怎么搞懂)。首先我们还是考虑朴素的匹配,暴力枚举匹配起点,遇到不匹配的点,就直接退出,进行下一个起始点开始的一轮匹配,这样的复杂度是平方级别的。但是kmp算法考虑的问题是,我们在这样的匹配过程中,会存在许多的无用匹配,当我们已经完成前n个字符的匹配时,如果在匹配串中存在前缀和后缀的相等情况,那么我们可以直接跳转起始点,而不用一个一个去枚举匹配了,这就是kmp的精髓。换句话说我们考虑匹配串自身的特性,在他和文本串匹配的过程中,如果存在前缀和后缀相同,我们可以直接把文本串已经被匹配的子串的后缀当成是匹配串的前缀来进行下一轮 的匹配,这样我们会省去更多的枚举。难点在于求解上文中所说的匹配串自身的特性,也就是第i个字符的时候,如果i+1这个字符匹配失效,我们的匹配动作该如何进行。所以在代码实现上要首先对需要匹配的串进行一个预处理,就是求出每一个点的next数组,即下一个字符如果失配的话,自动机的动作。
#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=100005;
char s[N],p[N];
int f[100005];
//KMP
void find (char *t,char *p,int *f) {
int n=strlen (t),m=strlen (p);
getfail(p,f);
int j=0;
for (int i=0;i<n;i++) {
while (j&&p[j]!=p[i]) j=f[j];
if (p[j]==t[i]) j++;
if (j==m) cout<<i-m-1<<endl;
}
}
int getfail (char *p,int *f) {
int len=strlen (p);
f[0]=0,f[1]=0;
for (int i=1;i<len;i++) {
int j=f[i];
while (j&&p[i]!=p[j]) j=f[j];
f[i+1]=p[i]==p[j]?j+1:0;
}
}
int main (){
return 0;
}
标签:ext mat 遇到 class 朴素 return ++ ret 自身
原文地址:https://www.cnblogs.com/hhlya/p/13227065.html