「POJ3693」Maximum repetition substring
Description
The repetition number of a string is defined as the maximum number R such that the string can be partitioned into R same consecutive substrings. For example, the repetition number of “ababab” is 3 and “ababa” is 1.
Given a string containing lowercase letters, you are to find a substring of it with maximum repetition number.
Input
The input consists of multiple test cases. Each test case contains exactly one line, which
gives a non-empty string consisting of lowercase letters. The length of the string will not be greater than 100,000.
The last test case is followed by a line containing a ‘#’.
Output
For each test case, print a line containing the test case number( beginning with 1) followed by the substring of maximum repetition number. If there are multiple substrings of maximum repetition number, print the lexicographically smallest one.
Sample Input
1 2 3 |
ccabababc daabbccaa # |
Sample Output
1 2 |
Case 1: ababab Case 2: aa |
题解
先穷举长度L,然后求长度为L 的子串最多能连续出现几次。首先连续出现1 次是肯定可以的,所以这里只考虑至少2 次的情况。假设在原字符串中连续出现2 次,记这个子字符串为S,那么S 肯定包括了字符r[0], r[L], r[L*2],r[L*3], ……中的某相邻的两个。所以只须看字符r[L*i]和r[L*(i+1)]往前和往后各能匹配到多远,记这个总长度为K,那么这里连续出现了K/L+1 次。
以上来自罗穗骞论文
往后匹配多远 r 用ST表求lcp即可。。。往前 l 就把串反过来再做一下。。
但是有可能求出来的最长串可以前移/后移几位
即开头可以在落在\([i-l,i-l+(l+r)mod\ L]\)
区间内字典序最小的还要用ST表找rank区间最值
ps:此题数据很水,发现我代码若有漏洞请留言
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<set> #include<ctime> #include<vector> #include<queue> #include<algorithm> #include<map> #include<cmath> #define inf 1000000000 #define pa pair<int,int> #define ll long long using namespace std; int n,mx,ans,ansl,ansr; int bin[30],Log[100005]; int mn[100005][17]; char ch[100005]; void rmq(int mn[100005][17],int *a) { for(int i=1;i<=n;i++)mn[i][0]=a[i]; for(int i=1;i<=Log[n];i++) for(int j=1;j<=n;j++) if(j+bin[i]-1<=n) mn[j][i]=min(mn[j][i-1],mn[j+bin[i-1]][i-1]); else break; } struct data{ int k,p,q; int rk[2][100005],sa[2][100005],v[100005],a[100005]; int h[100005],mn[100005][17]; void ini(){ memset(a,0,sizeof(a)); memset(v,0,sizeof(v)); memset(rk,0,sizeof(rk)); } void cal(int *sa,int *rk,int *SA,int *RK){ for(int i=1;i<=n;i++)v[rk[sa[i]]]=i; for(int i=n;i;i--) if(sa[i]>k) SA[v[rk[sa[i]-k]]--]=sa[i]-k; for(int i=n-k+1;i<=n;i++) SA[v[rk[i]]--]=i; for(int i=1;i<=n;i++) RK[SA[i]]=RK[SA[i-1]]+(rk[SA[i]]!=rk[SA[i-1]]||rk[SA[i]+k]!=rk[SA[i-1]+k]); } void getsa(){ p=0,q=1; for(int i=1;i<=n;i++)v[a[i]]++; for(int i=1;i<=30;i++)v[i]+=v[i-1]; for(int i=1;i<=n;i++) sa[p][v[a[i]]--]=i; for(int i=1;i<=n;i++) rk[p][sa[p][i]]=rk[p][sa[p][i-1]]+(a[sa[p][i]]!=a[sa[p][i-1]]); for(k=1;k<n;k<<=1,swap(p,q)) cal(sa[p],rk[p],sa[q],rk[q]); } void geth(){ k=0; for(int i=1;i<=n;i++) if(rk[p][i]==1)h[rk[p][i]]=0; else { int j=sa[p][rk[p][i]-1]; while(a[i+k]==a[j+k])k++; h[rk[p][i]]=k;if(k>0)k--; } } void pre(){ getsa();geth();rmq(mn,h); } int lcp(int x,int y){ x=rk[p][x],y=rk[p][y]; if(x>y)swap(x,y);x++; int t=Log[y-x+1]; return min(mn[x][t],mn[y-bin[t]+1][t]); } }c[2]; int query(int x,int y) { int t=Log[y-x+1]; return min(mn[x][t],mn[y-bin[t]+1][t]); } void solve(int L) { int l=0,r=0,t; for(int i=1;i+L<=n;i+=L) if(ch[i]==ch[i+L]) { r=c[0].lcp(i,i+L),l=c[1].lcp(n-i+2,n-i-L+2); if((l+r)/L+1>mx) mx=(l+r)/L+1,ans=inf; if((l+r)/L+1==mx) { t=query(i-l,i-l+(l+r)%L); if(t<ans) { ans=t; ansl=c[0].sa[c[0].p][t],ansr=ansl+mx*L-1; } } } } int main() { bin[0]=1;for(int i=1;i<20;i++)bin[i]=bin[i-1]<<1; Log[0]=-1;for(int i=1;i<=100000;i++)Log[i]=Log[i/2]+1; int tst=0; while(scanf("%s",ch+1)) { if(ch[1]=='#')break; tst++;printf("Case %d: ",tst); c[0].ini();c[1].ini(); n=strlen(ch+1); for(int i=1;i<=n;i++)c[0].a[i]=ch[i]-'a'+1; for(int i=1;i<=n;i++)c[1].a[i]=ch[n-i+1]-'a'+1; c[0].pre();c[1].pre(); rmq(mn,c[0].rk[c[0].p]); mx=1;ans=inf; for(int i=1;i<=n;i++) if(c[0].rk[c[0].p][i]<ans) ans=c[0].rk[c[0].p][i],ansl=ansr=i; for(int i=1;i<=n;i++)solve(i); for(int i=ansl;i<=ansr;i++) putchar(ch[i]); puts(""); } return 0; } |
好羡慕黄学长的代码总能打的简洁
Orz
Fifa Coins
Thank you, I’ve just been looking for information approximately this topic for a long time and yours is the greatest I’ve discovered till now. But, what about the conclusion? Are you sure concerning the source?|