[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 }

 

posted @ 2019-08-06 23:13  conver^_^  阅读(198)  评论(0编辑  收藏  举报