Title Link: http://www.spoj.com/problems/REPEATS/en/
Test instructions: First defines the repetition of a string. That is, a string repeats the K-th composition by a substring. Then the largest k is the repetition of the string. Now given a string of length n, the maximum number of repetitions is obtained.
Idea: According to the << suffix array-a powerful tool to deal with strings >> ideas, the first poor lifting length L, and then to find the length of the substring of L can be a number of consecutive occurrences. It is certainly possible to have 1 consecutive occurrences, so it is only considered at least 2 times in this case. Assuming that the original string appears consecutively 2 times, remember that substring is s, then s must include the character r[0], r[l], r[l*2],r[l*3], ... One of the adjacent two. So just look at the characters R[l*i] and r[l* (i+1)] forward and backward can be matched to how far, remember this total length of k, then there is a succession of k/l+1 times. Finally see what the maximum value is.
Here's my understanding of this idea, first enumerate the length l nothing to say, and then assume that the position I belongs to the first paragraph of the answer string, then consider the answer is repeated more than 2 times, then the position I must and position i+l match, if the longest common prefix to match is Len, Then the substring with I as the starting length of Len repeats len/l+1 times, but this is only the case of I for the starting point, considering I not for the case of the starting point, if Len is not a multiple of L, it is not enough to let the substring repeat again, so we can consider the len%l from I and i+ L match forward, if you can match [pre=l-(len%l)] characters, then you can repeat again, equivalent to the starting point of the answer character is i-pre, the number of repetitions is (len/l+1) +1, the following +1 is equivalent to the previous extra characters and I forward matching to fill up the number of repetitions. You can then determine whether the longest public prefix of the position i-pre and I+l-pre is greater than or equal to the character (pre) that needs to be matched, or if the forward direct violence match matches the pre. You might ask why you just need to go ahead and match the pre-character to judge, rather than the forward match. Is the answer not better? , if I and i+l forward can match pre+k*l characters, then the answer must be calculated on the I enumeration to i-k*l, so just match the previous pre characters. For the longest common prefix of the two locations and the height of the suffix array is preprocessed with RMQ, then O (1) can be queried.
The time of the exhaustive length L is N, and the time for each calculation is n/l. Therefore the time complexity of the entire procedure is O (n/1+n/2+n/3+......+n/n) =o (NLOGN).
#define_crt_secure_no_deprecate#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<string>#include<queue>#include<vector>#include<time.h>#include<cmath>using namespaceStd;typedefLong Long intLL;Const intMAXN =50000+5;intcmpint*r,intAintBintl) { returnR[a] = = R[b] && r[a + l] = = R[b +l];}intWA[MAXN], WB[MAXN], WV[MAXN], WS[MAXN];voidDaint(RNint*sa,intNintm) { intI, J, p, *x = WA, *y = WB, *T; for(i =0; I < m; i++) {Ws[i] =0; } for(i =0; I < n; i++) {Ws[x[i] = r[i]]++; } for(i =1; I < m; i++) {Ws[i] + = ws[i-1]; } for(i = n-1; I >=0; i--) {Sa[--ws[x[i]] =i;} for(j =1, p =1; p<n; J *=2, M =p) { for(P =0, i = n-j; I < n; i++) {y[p++] =i;} for(i =0; I < n; i++) { if(Sa[i] >= j) {y[p++] = Sa[i]-J;} } for(i =0; I < n; i++) {Wv[i] =X[y[i]];} for(i =0; I < m; i++) {Ws[i] =0; } for(i =0; I < n; i++) {ws[wv[i]]++; } for(i =1; I < m; i++) {Ws[i] + = ws[i-1]; } for(i = n-1; I >=0; i--) {Sa[--ws[wv[i]] =y[i];} for(t = x, x = y, y = t, p =1, x[sa[0]] =0, i =1; I < n; i++) {X[sa[i]]= CMP (y, Sa[i-1], Sa[i], j)? Ns1: p++; } } return;}intRANK[MAXN], HEIGHT[MAXN],SA[MAXN];voidCalheight (int(RNint*sa,intN) { intI, j, k =0; for(i =1; I <= N; i++) {Rank[sa[i]] =i;} for(i =0; I < n; height[rank[i++]] =k) { for(K. k--:0, j = Sa[rank[i]-1]; R[i + K] = = R[j + K]; k++); } return;}intrmq[maxn],mm[maxn],best[ -][MAXN];voidINITRMQ (intN) { intI, J, A, B; for(mm[0] = -1, i =1; I <= N; i++) Mm[i]= ((i& (i-1)) ==0) ? Mm[i-1] +1: Mm[i-1]; for(i =1; I <= N; i++) best[0][i] =i; for(i =1; I <= Mm[n]; i++) for(j =1; J <= N +1- (1<< i); J + +) {a= Best[i-1][j]; b= Best[i-1][j + (1<< (I-1))]; if(Rmq[a]<rmq[b]) best[i][j] =A; ElseBEST[I][J] =b; } return;}intASKRMQ (intAintb) { intT; T= Mm[b-a +1]; B-= (1<< T)-1; A= Best[t][a]; b =Best[t][b]; returnRMQ[A]<RMQ[B]?a:b;}intLcpintAintb) { intT; A= Rank[a]; b =Rank[b]; if(A>B) {T = A; a = b; b =T;} return(HEIGHT[ASKRMQ (A +1, b)]);}intR[MAXN], T, Len;Charstr;voidsolve () {intans=0; for(intL =1; L <= Len; l++){ for(inti =0; i + l<len; i + =L) { intLcplen = LCP (i, i + L);//the longest common prefix for I and i+l intTMP = lcplen/l +1;//number of repetitions at this time intSur = (l-lcplen%l);//The number of remaining matches that can be matched forward intPrei = I-sur;//position to match forward if(Prei >=0&& Prei + L < LEN&&LCP (prei,prei+l) >=L) {tmp++;//does not cross and the longest public prefix is greater than L, or more than the remaining required number can be} ans=max (ans, TMP); }} printf ("%d\n", ans);}intMain () {//#ifdef Kirito//freopen ("In.txt", "R", stdin);//freopen ("OUT.txt", "w", stdout);//#endif//int start = Clock ();scanf"%d", &t); while(t--) {scanf ("%d\n", &Len); for(inti =0; i < Len; i++) {scanf ("%c\n", &str); R[i]= str-'a'+1; } R[len]=0; Da (R, SA, Len+1,3);//because the topic input only ' a ' and ' B ', so the maximum character is 3calheight (R, SA, Len); for(inti =1; I <= Len; i++) {Rmq[i] = height[i];}//Initialize RMQINITRMQ (len);//Calculate RMQsolve (); }//#ifdef Local_time//cout << "[Finished in" << clock ()-Start << "MS" << Endl;//#endif return 0;}
Spoj REPEATS suffix Array