Smiling & Weeping
---- 我与月亮,进行了一次深夜谈话
它与我谈论太阳,而我与它谈论你。
题目链接:P3435 [POI2006] OKR-Periods of Words - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
思路:其实也就是kmp拓展,求s与s的每个后缀的LCP(最长公共前缀),但是这样超时,需要一个小小的优化(记录跳转即step[k],跳到可以上一个可以实现的地方,尽量保持复杂度在线性),同时s[i] == s[0]时,直接使ans += i;
Talk is cheap , show me the code
1 #include<bits/stdc++.h> 2 using namespace std; 3 int n , Next[1000100] , step[1000100]; 4 char str[1000100]; 5 void getNext(char *c){ 6 int len = strlen(c); 7 int p = 0 , k = 1 , l; 8 Next[0] = len; 9 while(p+1 < len && c[p] == c[p+1]) p++; 10 Next[1] = p; 11 for(int i = 2; i < len; i++){ 12 p = k+Next[k]-1; 13 l = Next[i-k]; 14 if(i+l <= p) Next[i] = l; 15 else{ 16 int j = max(0 , p-i+1); 17 while(i+j < len && c[i+j] == c[j]) j++; 18 Next[i] = j; 19 k = i; 20 } 21 } 22 } 23 int main() 24 { 25 long long ans = 0; 26 int q=0 , k; // q代表周期,k代表最远到达的距离 27 scanf("%d",&n); scanf("%s",str); 28 getNext(str); 29 for(int i = 1; i < n; i++){ 30 if(str[i] == str[0]){ 31 ans += i; 32 } else { 33 int r = i-1 , tem = r; 34 while(Next[r] < i-r+1 && r >= (i+1)/2){ 35 if(step[r] && step[r] < r) // 警惕bug,可能有step[r]==r,陷入死循环 36 r = step[r]; 37 else r--; 38 } 39 if(r >= (i+1)/2 && Next[r] >= i-r+1) ans += r; 40 step[tem] = r; 41 } 42 } 43 printf("%lld\n",ans); 44 return 0; 45 }
一棵树,一块岩石,一朵云
文章到此结束,我们下次再见
标签:1000100,int,len,Next,step,拓展,应用,kmp From: https://www.cnblogs.com/smiling-weeping-zhr/p/17686351.html