多校打下来第一次成功补题(?你在干嘛)
套板子完事,主要是之前没搞懂扩展KMP到底是什么,KMP也没搞清楚,这回顺带加深了一下印象。
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6629
题意:给出一个用于求在一个给定字符串中求每一位的后缀(含自己)与这个字符串的最长相同的长度的算法,问你对于给出的字符串执行这个算法,会进行多少次这个算法中那个字符与字符的比较过程(详见题目)。
思路:用拓展KMP里求辅助数组的代码跑一遍,我们就可以得到每一位的最长字串的长度,然后因为问的是比较次数,那么只要这一位的位置加上它的子串长没用超过字符串的最后一位,就说明它会在统计时还要加上一次比较次数,也就是在统计它的字串长度时它和下一位比较并且匹配失败的那一次。
说得比较绕,还是放代码吧。
1 #include<iostream> 2 #include<cstdio> 3 #include<set> 4 #include<stdio.h> 5 #include<string.h> 6 #include<math.h> 7 #include<vector> 8 #include<stdlib.h> 9 #include<queue> 10 #include<algorithm> 11 #include<map> 12 #include<stack> 13 using namespace std; 14 char c[1000005]; 15 int nex[1000005]; 16 int main() 17 { 18 int t; 19 scanf("%d",&t); 20 while(t--) 21 { 22 scanf("%s",c); 23 long long s=0; 24 int len=strlen(c); 25 nex[0]=len; 26 int a=0,p=0;//p 当前最长匹配距离 a最长匹配距离对应的点 27 for(int i=1;i<len;i++) 28 { 29 if(i>=p||i+nex[i-a]>=p)//假如i在最长匹配距离的点之外或其预期距离超出p 30 { 31 if(i>=p) 32 { 33 p=i; 34 } 35 while(p<len&&c[p]==c[p-i]) 36 { 37 p++; 38 } 39 nex[i]=p-i; 40 a=i; 41 } 42 else//假如没有超出的可能,直接得出结论 43 { 44 nex[i]=nex[i-a]; 45 } 46 } 47 for(int i=1;i<len;i++) 48 { 49 //printf("%d ",nex[i]); 50 s+=nex[i]; 51 if(i+nex[i]<len)//访问距离未超出字符串末尾就会再访问下一位 52 { 53 s++; 54 //printf("1 "); 55 } 56 } 57 printf("%lld ",s); 58 } 59 return 0; 60 }