题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=3971
题目大意:求重复次数不小于k次的最长子串(可覆盖),并输出最右边出现的位置。
题目思路:后缀数组加二分答案。注意k为1的情况。
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<string> #include<queue> #include<algorithm> #include<vector> #include<stack> #include<list> #include<iostream> #include<map> using namespace std; #define inf 0x3f3f3f3f #define M 41000 int max(int a,int b) { return a>b?a:b; } int min(int a,int b) { return a<b?a:b; } int height[M],rank[M],r[M],sa[M]; int ts[M],ta[M],tb[M],tv[M],pos; bool cmp(int *y,int a,int b,int l) { return y[a]==y[b]&&y[a+l]==y[b+l]; } void da(int n,int m) { int i,j,*x=ta,*y=tb,p; for(i=0;i<m;i++) ts[i]=0; for(i=0;i<n;i++) ts[x[i]=r[i]]++; for(i=1;i<m;i++) ts[i]+=ts[i-1]; for(i=n-1;i>=0;i--) sa[--ts[x[i]]]=i; for(j=1,p=1;p<n;j*=2,m=p) { p=0; for(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<m;i++) ts[i]=0; for(i=0;i<n;i++) tv[i]=x[y[i]]; for(i=0;i<n;i++) ts[tv[i]]++; for(i=1;i<m;i++) ts[i]+=ts[i-1]; for(i=n-1;i>=0;i--) sa[--ts[tv[i]]]=y[i]; swap(x,y); x[sa[0]]=0; p=1; for(i=1;i<n;i++) { if(cmp(y,sa[i-1],sa[i],j)) x[sa[i]]=p-1; else x[sa[i]]=p++; } } } void calh(int n) { int i,k,tmp; for(i=1;i<=n;i++) rank[sa[i]]=i; k=0; for(i=0;i<n;i++) { tmp=sa[rank[i]-1]; for(;r[i+k]==r[tmp+k];k++) ; height[rank[i]]=k; k?--k:0; } } int check(int n,int k,int len) { int num=1,i; for(i=2;i<=n;i++) { if(height[i]<len) num=1; else { num++; if(num>=k) return true; } } return false; } void getans(int n,int k,int len) { int num=1,i; pos=0; int rec; rec=sa[1]; for(i=2;i<=n;i++) { if(height[i]<len) { num=1; rec=sa[i]; } else { num++; rec=max(rec,sa[i]); if(num>=k) pos=max(pos,rec); } } } char s[M]; int main() { int i,k,len; while(scanf("%d",&k),k) { scanf("%s",s); len=strlen(s); for(i=0;i<len;i++) r[i]=s[i]-'a'+1; r[i]=0; if(k==1) { printf("%d %d\n",len,0); continue; } da(len+1,27); calh(len); int le,ri,mid; le=1;ri=len; while(le<=ri) { mid=(le+ri)>>1; if(check(len,k,mid)) le=mid+1; else ri=mid-1; } getans(len,k,ri); if(ri==0) printf("none\n"); else printf("%d %d\n",ri,pos); } }