#include<cmath> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=100005; int ws[N],wv[N],wa[N],wb[N]; int Rank[N],height[N],sa[N],l; char s[N],xiao; int dp[N][25]; int cmp(int *r,int a,int b,int l) { return r[a]==r[b]&&r[a+l]==r[b+l]; } void da(char *r,int *sa,int n,int m) { int i,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<m;i++) ws[i]=0; for(i=0;i<n;i++) ws[wv[i]=x[y[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)?p-1:p++; } } void calheight(char *r,int *sa,int n) { int i,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++); } void RMQ()//RMQ初始化 { int i,j,m; m=(int)(log((double)l)/log(2.00)); for(i=1;i<=l;i++) dp[i][0]=height[i]; for(j=1;j<=m;j++) for(i=1;i+(1<<j)-1<=l;i++) dp[i][j]=min(dp[i][j-1],dp[i+(1<<(j-1))][j-1]); } int lcp(int x,int y)//求最长公共前缀 { int t; x=Rank[x];y=Rank[y]; if(x>y) swap(x,y); x++; t=(int)(log(double(y-x+1))/log(2.00)); return min(dp[x][t],dp[y-(1<<t)+1][t]); } void solve()//求最多重复次数子串 { int i,j,max=1,f=0,l1,num=0,t,node=1,k,cnt,p; for(i=;i<=l/2;i++)//i<=len/2优化了,枚举长度不同的循环节 { for(j=0;j+i<l;j+=i)//枚举子串起点 { if(s[j]!=s[j+i])//剪枝 continue; l1=lcp(j,j+i);//求j位置和j+i位置的最长公共前缀 num=l1/i+1;//j...j+i-1为循环节 p=j;//起点 t=i-l1%i;//因为l1不一定是循环串长度的整数倍,而且我们之前枚举j的时候是每次递增i的可能会漏掉 cnt=0;//一些可能成为串起点的,重复次数更多的节点,t记录的时在j前面再出现几个满足相等的字符就能构成循环节不同,但循环次数为num+1的子串 for(k=j-1;k>=0&&k+i>j&&s[k]==s[k+i];k--)//寻找重复次数更多或是rank值更小子串的过程 { cnt++; if(cnt==t) { num++; p=k; } else if(Rank[k]<Rank[p]) p=k; } if(max<num) { f=p; max=num; node=i; } else if(max==num&&Rank[f]>Rank[p]) { f=p; node=i; } } } if(max==1) { printf("%c\n",xiao); return ; } for(i=f;i<=f+max*node-1;i++) printf("%c",s[i]); printf("\n"); } int main() { int kase=0,i; while(scanf("%s",s)!=EOF&&s[0]!='#') { l=strlen(s); xiao='z'+1; for(i=0;i<l;i++) if(s[i]<xiao) xiao=s[i]; s[l]='0'; da(s,sa,l+1,'z'+1); calheight(s,sa,l); RMQ(); printf("Case %d: ",++kase); solve(); } return 0; }