[Link] title
# 10038. "one through 2.1 Exercise 4" A Horrible Poem
Reference [blog]
A Horrible Poem (string hash + number theory)
Description [title]
Is given by the lower case letters a string S S, then gives Q Q a query, the answer requires S S shortest substring of a loop section.
If the string B B string A circular section A, then A A may be composed of B was repeated several times to give B.
[Algorithm] - for first length L E n- substring len, the cycle length of the section x Sufficient Conditions of x: [ . 1 , L E n- - x ] [. 1, len-x] is equal to the hash value string [ X + . 1 , L E n- ] [X +. 1, len] hash value string.
Minimum Cycle length is assumed that the section of the original string length len apparently len * k. If there is only k, k, and the prime factor decomposition sequentially, in addition to each sample k, the obtained k . k. Len and the product is still circulating section, the use of this property. Washed successively with prime factor i i test than n, if the cycle is still removed section on the i belongs to k, it is removed, leaving the result len.
[Code]:
1 #include<cstdio> 2 #include<bitset> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 typedef unsigned long long ULL ; 7 const int N = 5e5+10; 8 ULL h[N],p[N],base = 131; 9 10 char str[N]; 11 int n,m,len,ans,tmp,L,R; 12 13 int prime[N],Min_p[N],cnt; 14 void Init(){ 15 //memset( is_prime , true , sizeof is_prime ); 16 int tot = 0 ; 17 for(int i=2;i<N;i++) { 18 if(!Min_p[i]) { 19 //if( i < 10 ) printf("%d\n",i); 20 prime[++tot]=i; 21 Min_p[i]=i; 22 } 23 for(int j=1;j<=tot;j++) { 24 if(prime[j]>Min_p[i]||prime[j]*i>N) break; 25 Min_p[prime[j]*i]=prime[j]; 26 } 27 } 28 cnt = tot ; 29 } 30 31 void get_Hash(){ 32 p[0] = 1; 33 for(int i=1;i<=len;i++){ 34 p[i] = p[i-1] * base ; 35 h[i] = h[i-1] * base + (ULL) str[i]; 36 } 37 } 38 39 bool Vaild( int L , int R , int k ){ 40 return h[R] - h[L+k-1] * p[len-k] == h[L + (len/k-1)*k - 1] - h[L-1] * p[len-k] ; 41 } 42 int main() 43 { 44 Init(); 45 //for(int i=1;i<10;i++) printf("%d\n",prime[i]); 46 scanf("%d%s%d",&n,str+1,&m); 47 48 49 len = strlen( str+1 ) ; 50 get_Hash(); 51 /* 52 for(int i=1;i<=len;i++){ 53 printf("%llu\n",h[i]); 54 } 55 */ 56 while( m-- ){ 57 scanf("%d%d",&L,&R); 58 len = tmp = ans = R - L + 1 ; 59 while( tmp != 1 ){ 60 int k = Min_p[tmp] ; 61 while( tmp % k == 0 && Vaild(L,R,ans/Min_p[tmp] ) ) 62 tmp /= k , ans /= k ; 63 while( tmp % k == 0 ) 64 tmp /= k ; 65 } 66 printf("%d\n",ans); 67 } 68 return 0 ; 69 }