[hdu-6629]string matching 扩展kmp 2019多校5
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6629
题目大意:给一个字符串s [0,...len-1] 求子串 si [ i,...len-1 ] 与 s的最长公共前缀, 即求所有子串后缀的最长公共前缀的长度;
给了一个暴力算法(每一个后缀子串都与原串从第一位开始比),求这个暴力算法要比较多少次。
题解:用扩展kmp求每个后缀子串si与原串s的最长公共前缀,然后如果就是后缀si,则比较次数+nex(si),否则+nex(si)+1 ,nex(si)为最长公共前缀长度
一个将扩展kmp清晰的博客链接:https://subetter.com/algorithm/extended-kmp-algorithm.html
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 int const maxn=1000100; 5 //扩展kmp:求t每一个后缀字符串匹配s最长前缀长度 6 /* 7 extend[i]:S[i]...S[n-1]与 T 的最长相同前缀的长度 8 next[i]: T[i]...T[m - 1]与 T 的最长相同前缀长度; 9 */ 10 int lent,nex[maxn]; 11 char t[maxn]; 12 long long ans; 13 void getnext(){ 14 lent=strlen(t); 15 int a=0,p=0;//p是最长的匹配到的位置,a是它开始匹的位置 16 nex[0]=lent; 17 for(int i=1;i<lent;i++){ 18 if(i>=p||i+nex[i-a]>=p){ 19 if(i>=p)p=i; 20 while(p<lent&&t[p]==t[p-i])p++; 21 nex[i]=p-i;a=i; 22 } 23 else nex[i]=nex[i-a]; 24 if(i+nex[i]==lent)ans+=nex[i]; 25 else ans+=nex[i]+1; 26 } 27 } 28 int main(){ 29 int Y; 30 scanf("%d",&Y); 31 while(Y--){ 32 scanf("%s",t); 33 ans=0; 34 getnext(); 35 cout<<ans<<endl; 36 } 37 return 0; 38 }