1. 程式人生 > >[POJ2406]Power Strings

[POJ2406]Power Strings

break turn pri 技術分享 ring 固定 show closed ()

傳送門

給定一個字符串 L,已知這個字符串是由某個字符串 S 重復 R 次而得到的,求 R 的最大值。

1.後綴數組

做法比較簡單,窮舉字符串 S 的長度 k,然後判斷是否滿足。判斷的時候,

先看字符串 L 的長度能否被 k 整除,再看 suffix(1)和 suffix(k+1)的最長公共

前綴是否等於 n-k。在詢問最長公共前綴的時候,suffix(1)是固定的,所以 RMQ 問題沒有必要做所有的預處理,只需求出 height 數組中的每一個數到

height[rank[1]]之間的最小值即可。

因為用的是倍增求後綴數組,TLE,然而不會 DC3,正確性。。。。不知道(但至少思路是對的,你敢質疑羅大牛?)

——代碼

技術分享
 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #define N 1000001
 5 #define min(x, y) ((x) < (y) ? (x) : (y))
 6 
 7 int len, n, m, ans;
 8 int buc[N], x[N], y[N], sa[N], rank[N], height[N], d[N];
 9 char s[N];
10 
11 inline void
build_sa() 12 { 13 int i, k, p; 14 for(i = 0; i < m; i++) buc[i] = 0; 15 for(i = 0; i < len; i++) buc[x[i] = s[i]]++; 16 for(i = 1; i < m; i++) buc[i] += buc[i - 1]; 17 for(i = len - 1; i >= 0; i--) sa[--buc[x[i]]] = i; 18 for(k = 1; k <= len; k <<= 1
) 19 { 20 p = 0; 21 for(i = len - 1; i >= len - k; i--) y[p++] = i; 22 for(i = 0; i < len; i++) if(sa[i] >= k) y[p++] = sa[i] - k; 23 for(i = 0; i < m; i++) buc[i] = 0; 24 for(i = 0; i < len; i++) buc[x[y[i]]]++; 25 for(i = 1; i < m; i++) buc[i] += buc[i - 1]; 26 for(i = len - 1; i >= 0; i--) sa[--buc[x[y[i]]]] = y[i]; 27 std::swap(x, y); 28 p = 1, x[sa[0]] = 0; 29 for(i = 1; i < len; i++) 30 x[sa[i]] = y[sa[i - 1]] == y[sa[i]] && y[sa[i - 1] + k] == y[sa[i] + k] ? p - 1 : p++; 31 if(p >= len) break; 32 m = p; 33 } 34 } 35 36 inline void build_height() 37 { 38 int i, j, k = 0; 39 for(i = 0; i < len; i++) rank[sa[i]] = i; 40 for(i = 0; i < len; i++) 41 { 42 if(!rank[i]) continue; 43 if(k) k--; 44 j = sa[rank[i] - 1]; 45 while(s[i + k] == s[j + k] && i + k < len && j + k < len) k++; 46 height[rank[i]] = k; 47 } 48 } 49 50 inline void RMQ_init() 51 { 52 int i, k; 53 k = rank[0], d[k] = len; 54 for(i = k - 1; i >= 0; i--) d[i] = min(d[i + 1], height[i + 1]); 55 for(i = k + 1; i < len; i++) d[i] = min(d[i - 1], height[i]); 56 } 57 58 inline int RMQ(int k) 59 { 60 return d[rank[k]]; 61 } 62 63 inline int solve() 64 { 65 int i; 66 for(i = 1; i <= len / 2; i++) 67 if(!(len % i)) 68 if(RMQ(i) == (len - i)) 69 return len / i; 70 return 1; 71 } 72 73 int main() 74 { 75 while(scanf("%s", s) && s[0] ^ .) 76 { 77 m = 256; 78 len = strlen(s); 79 build_sa(); 80 build_height(); 81 RMQ_init(); 82 printf("%d\n", solve()); 83 } 84 return 0; 85 }
View Code

可見後綴數組並不是正解。

2.kmp(沒細致研究過,以後補)

[POJ2406]Power Strings