Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 5946   Accepted: 1799

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

ccabababc
daabbccaa
#

Sample Output

Case 1: ababab
Case 2: aa
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <queue>
#include <algorithm>
#include <map>
#include <cmath>
#include <iomanip>
#define INF 99999999
typedef long long LL;
using namespace std; const int MAX=100000+10;
int *rank,r[MAX],sa[MAX],height[MAX],L[MAX];
int wa[MAX],wb[MAX],wm[MAX],f[MAX][32];
char s[MAX]; bool cmp(int *r,int a,int b,int l){
return r[a] == r[b] && r[a+l] == r[b+l];
} void makesa(int *r,int *sa,int n,int m){
int *x=wa,*y=wb,*t;
for(int i=0;i<m;++i)wm[i]=0;
for(int i=0;i<n;++i)wm[x[i]=r[i]]++;
for(int i=1;i<m;++i)wm[i]+=wm[i-1];
for(int i=n-1;i>=0;--i)sa[--wm[x[i]]]=i;
for(int i=0,j=1,p=0;p<n;j=j*2,m=p){//j表示合并的子串长度
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)wm[i]=0;
for(i=0;i<n;++i)wm[x[y[i]]]++;
for(i=1;i<m;++i)wm[i]+=wm[i-1];
for(i=n-1;i>=0;--i)sa[--wm[x[y[i]]]]=y[i];
for(t=x,x=y,y=t,i=p=1,x[sa[0]]=0;i<n;++i){//求新的x,相当于rank,但是相同的子串要排名相同
x[sa[i]]=cmp(y,sa[i],sa[i-1],j)?p-1:p++;//判断子串suffix(sa[i])与suffix(sa[i-1])是否相同并且确定排名
}
}
rank=x;
} /*在计算好height[rank[i]]后,对于height[rank[i+1]],如果sa[rank[i]-1]的首字母和sa[rank[i]]首字母相同
则rank[i+1]肯定在rank[sa[rank[i]-1]+1]后面,根据排名为a,b的子串的最长公共前缀为[a,b]中最小的
所以i+1和sa[rank[i+1]-1]的公共前缀>=height[rank[i]]-1即>=k-1;
如果sa[rank[i]-1]的首字母和sa[rank[i]]首字母不相同,则上一次的k就是0,所以无影响
*/
void calheight(int *r,int *sa,int n){
for(int i=0,j=0,k=0;i<n;height[rank[i++]]=k){
for(k?--k:0,j=sa[rank[i]-1];r[i+k] == r[j+k];++k);
}
} void InitRMQ(int n){
for(int i=1;i<=n;++i)f[i][0]=height[i];//初始化从i开始区间长度为2^0的最值
int l=log(n*1.0)/log(2.0);//2*l<=n
for(int j=1;j<=l;++j){
for(int i=1;i+(1<<j)-1<=n;++i){//i+2^j-1<=n
f[i][j]=min(f[i][j-1],f[i+(1<<(j-1))][j-1]);//i+2^j-1 - (i+2^(j-1))+1=2^(j-1)
}
}
} int LCP(int i,int j){//求rank[i]与rank[i]+1,ran[i]+1与rank[i]+2...的最长公共前缀中的最值,即height[rank[i]+1]~height[rank[j]]的最值
i=rank[i],j=rank[j];
if(i>j)swap(i,j);
++i;
int l=log(j-i+1.0)/log(2.0);//2^l<=j-i+1
return min(f[i][l],f[j-(1<<l)+1][l]);
} int main(){
int Case=0;
while(scanf("%s",s),s[0] != '#'){
int n=0;
for(n=0;s[n] != '\0';++n)r[n]=s[n];
r[n]=0;
makesa(r,sa,n+1,256);
calheight(r,sa,n);
InitRMQ(n);
int sum=0,size=0,x=sa[1],y=sa[1]+1;
for(int j=1;j<=n;++j){//对于长度为j的循环节,sum记录循环次数
for(int i=0;i+j<n;i+=j){
if(s[i] == s[i+j]){
int len=LCP(i,i+j);//向后匹配
int num=len/j;
int k=i-(j-len%j);
if(k>=0 && len%j && LCP(k,k+j)>=len)++num;//向前匹配
if(num == sum)L[++size]=j;//L记录得到最多循环次数的可能的子串长度
else if(num > sum)sum=num,L[size=0]=j;
}
}
}
for(int i=1;i<=n && sum;++i){//求哪个子串可以循环sum次
for(int j=0;j<=size;++j){
if(sa[i]+L[j]>=n)continue;
int len=LCP(sa[i],sa[i]+L[j]);
if(len/L[j] == sum){x=sa[i],y=sa[i]+(sum+1)*L[j],sum=0;break;}
}
}
printf("Case %d: ",++Case);
for(int i=x;i<y;++i)printf("%c",s[i]);
printf("\n");
}
return 0;
}

poj3693之后缀数组的更多相关文章

  1. poj3693(后缀数组)

    poj3693 题意 给出一个串,求重复次数最多的连续重复子串,输出字典序最小的. 分析 论文 例8(P21). Sparse-Table算法预处理出任意两个后缀串的LCP. code #includ ...

  2. POJ3693(SummerTrainingDay10-J 后缀数组)

    Maximum repetition substring Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 10241   Ac ...

  3. 【poj3693】Maximum repetition substring(后缀数组+RMQ)

    题意:给定一个字符串,求重复次数最多的连续重复子串. 传说中的后缀数组神题,蒟蒻真的调了很久才对啊.感觉对后缀数组和RMQ的模版都不是很熟,导致还是会有很多各种各样的小错误= = 首先,枚举重复子串的 ...

  4. POJ3693 Maximum repetition substring [后缀数组 ST表]

    Maximum repetition substring Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 9458   Acc ...

  5. POJ3693 Maximum repetition substring 后缀数组

    POJ - 3693 Maximum repetition substring 题意 输入一个串,求重复次数最多的连续重复字串,如果有次数相同的,则输出字典序最小的 Sample input ccab ...

  6. 关于后缀数组的倍增算法和height数组

    自己看着大牛的论文学了一下后缀数组,看了好久好久,想了好久好久才懂了一点点皮毛TAT 然后就去刷传说中的后缀数组神题,poj3693是进化版的,需要那个相同情况下字典序最小,搞这个搞了超久的说. 先简 ...

  7. 【UVA10829】 L-Gap Substrings (后缀数组)

    Description If a string is in the form UVU, where U is not empty, and V has exactly L characters, we ...

  8. 【uva10829-求形如UVU的串的个数】后缀数组+rmq or 直接for水过

    题意:UVU形式的串的个数,V的长度规定,U要一样,位置不同即为不同字串 https://uva.onlinejudge.org/index.php?option=com_onlinejudge&am ...

  9. 【距离GDOI:131天】 后缀数组完毕

    用了近两周的时间,终于把罗神那篇后缀数组应用看完了,题目也写了一遍,T了无数次...详见前几篇博文... 后缀数组很重要的是那个height数组,可以用来做各种奇奇怪怪的东西...常用方法去是去二分, ...

随机推荐

  1. ubantu root 默认密码

    安装完Ubuntu后忽然意识到没有设置root密码,不知道密码自然就无法进入根用户下.到网上搜了一下,原来是这麽回事.Ubuntu的默认root密码是随机的,即每次开机都有一个新的root密码.我们可 ...

  2. Spring Boot MyBatis 连接数据库

    最近比较忙,没来得及抽时间把MyBatis的集成发出来,其实mybatis官网在2015年11月底就已经发布了对SpringBoot集成的Release版本,Github上有代码:https://gi ...

  3. stl 迭代子的失效

    迭代子是STL中很重要的特性,但是其很脆弱(我个人认为),因为使用它的条件很苛刻,一不小心就失效了.其在两中情况下可能会失效. 1.当容器有插入操作时 在初始化了迭代子后,如果容器有插入操作时,迭代子 ...

  4. UIWindow 详解

    UIWindow对象是所有UIView的根视图,管理和协调的应用程序的显示.分发事件给View.UIWindow类是UIView的子类,可以看作是特殊的UIView.一般应用程序只有一个UIWindo ...

  5. UVALive 6947 Improvements(DP+树状数组)

    [题目链接] https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=sho ...

  6. HDU 4957 Poor Mitsui

    题解:记答案为ans,已知,对一个确定的顺序,计算所用的时间长短就是从最后向前计算,计算方法如下: ans+=(p[i].b+ans*p[i].a)/(v-p[i].a) 那么,应该如何调整顺序使得答 ...

  7. CentOS ips bonding

    centos ip bonding 一个网卡多个ips,多个网口一个ip 1,配置一个网卡多ips的情况cp /etc/sysconfig/network-scripts/ifcfg-eth0 /et ...

  8. <td style="word-break:break-all"> 在html中控制自动换行

    在html中控制自动换行   其实只要在表格控制中添加一句 <td style="word-break:break-all">就搞定了. 其中可能对英文换行可能会分开一 ...

  9. golang printf

    1:  打印包括字段在内的实例的完整信息 同 %+V fmt.Printf("Hello world! %v","hufeng") 输出:Hello world ...

  10. xml 充当简易数据库

    后台: 写入节点 public static void Update(string path, string node, string attribute, string value) { try { ...