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. VS2010/MFC对话框:一般属性页对话框的创建及显示

    一般属性页对话框的创建及显示 本节将介绍一般属性页对话框的创建和显示. 实际上,一般属性页对话框的创建和显示过程和向导对话框是很类似的.鸡啄米将上一节中的向导对话框进行少量修改,使其成为一般属性页对话 ...

  2. c++实现将表达式转换为逆波兰表达式

    https://github.com/Lanying0/lintcode 所属: 数据结构->线性结构->栈 问题: 给定一个表达式字符串数组,返回该表达式的逆波兰表达式(即去掉括号). ...

  3. 求高手帮忙解决一下问题Java Web Cookie实例

    package cn.com; import java.io.IOException; import java.io.PrintWriter; import java.util.LinkedHashM ...

  4. Git怎样同一时候删除多个仓下的同一个分支

    每次下载完代码我们都会在本地通过repo start my_local --all建立分支,这样我们下载的代码在每一个仓下都有一个名叫my_local的分支,有些时候我们因为须要还会建立其它分支,当我 ...

  5. html网页编码问题

    之前碰到过一些html编码乱码问题,都理解的模模糊糊,问了别人解释的也是模模糊糊.近期要做前端这个问题研究了下仅仅须要两句话就能非常清楚的解释了(之前问的那些人是不是自己都没理解非常郁闷.) < ...

  6. Node.js笔记3

    ###Node.js核心模块 1. 全局对象 Node.js中能够访问到的都是global的属性 **process它用于描述当前 Node.js 进程状态的对象,提供了一个与操作系统的简单接口.** ...

  7. offsetParent 到底是哪一个?

    前言 温故而知新.遇到offsetParent这个知识点,发现书上讲的不够详细.于是看了看豪情的博客,发现讲得很具体,收藏一下. 正文 不同情况 没有已定位的父节点,且自身position:relat ...

  8. Jquery 方法大全

    一.JQuery常用的方法 :(JQuery中90%都是方法,没有参数是获取,带参数是设置) $("#id").css('backgroundColor','blue'); .cs ...

  9. 如何用cocoapods 来管理项目中的第三方框架?

     一.安装 1.如果以前安装过,升级到10.10后工作不正常,可以先删除cocoapods $ sudo gem uninstall cocoapods ----------------------- ...

  10. iOS 设置状态栏的颜色

    1.在plist文件中设置如下属性: 2.在delegate中设置 [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarSt ...