重复次数最多的字串,我们可以枚举循环节的长度。

然后正反两次LCP,然后发现如果长度%L有剩余的情况时,答案是在一个区间内的。

所以需要找到区间内最小的rk值。

两个后缀数组,四个ST表,$\Theta(n\log n)$

就可以解决了

空间卡死了,瞎晶胞卡过去了。

#include <map>
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define F(i,j,k) for (int i=j;i<=k;++i)
#define D(i,j,k) for (int i=j;i>=k;--i)
#define ll long long
#define mp make_pair
#define maxn 200010
#define inf 0x3f3f3f3f int _log[maxn],kas=0; struct Suffix_Array{
int s[maxn];
int cnt[maxn],sa[maxn],tmp[maxn],rk[maxn],h[maxn];
int st[2][maxn][18];
void build(int n,int m)
{
s[n]=0; n++; int i,j,k;
F(i,0,n+2) sa[i]=tmp[i]=rk[i]=h[i]=0;
F(i,0,m-1) cnt[i]=0;
F(i,0,n-1) cnt[rk[i]=s[i]]++;
F(i,1,m-1) cnt[i]+=cnt[i-1];
F(i,0,n-1) sa[--cnt[rk[i]]]=i;
for (k=1;k<=n;k<<=1)
{
F(i,0,n-1)
{
int j=sa[i]-k;
if (j<0) j+=n;
tmp[cnt[rk[j]]++]=j;
}
sa[tmp[cnt[0]=0]]=j=0;
F(i,1,n-1)
{
if (rk[tmp[i]]!=rk[tmp[i-1]]||rk[tmp[i]+k]!=rk[tmp[i-1]+k]) cnt[++j]=i;
sa[tmp[i]]=j;
}
memcpy(rk,sa,n*sizeof(int));
memcpy(sa,tmp,n*sizeof(int));
if (j>=n-1) break;
}
for (int i=k=0;i<n;h[rk[i++]]=k)
for (k?k--:0,j=sa[rk[i]-1];s[i+k]==s[j+k];k++);
F(i,0,n-1) st[0][i][0]=h[i];
F(i,1,17) F(j,0,n-(1<<i)) st[0][j][i]=min(st[0][j][i-1],st[0][j+(1<<(i-1))][i-1]);
F(i,0,n-1) st[1][i][0]=rk[i];
F(i,1,17) F(j,0,n-(1<<i)) st[1][j][i]=min(st[1][j][i-1],st[1][j+(1<<(i-1))][i-1]);
}
int query(int id,int l,int r)
{
int k=_log[r-l+1];
return min(st[id][l][k],st[id][r-(1<<k)+1][k]);
}
int lcp(int a,int b)
{
int aa=rk[a],bb=rk[b];
return query(0,min(aa,bb)+1,max(aa,bb));
}
}SA,SB; int ansl,ansr,mx,ans,n,minn;char s[maxn]; void solve(int L)
{
for (int i=0;i+L<n;i+=L)
if (s[i]==s[i+L])
{
int l=SA.lcp(i+1,i+L+1),r=SB.lcp(n-i-1,n-i-L-1);
if (l+r<L) continue;
if ((l+r)/L+1>mx) mx=(l+r)/L+1,ans=inf;
if ((l+r)/L+1==mx)
{
int tmp=SA.query(1,i-r+1,i-r+1+(l+r)%L);
if (tmp<ans)
{
ans=tmp;
ansl=SA.sa[tmp]; ansr=ansl+mx*L-1;
}
}
}
} int main()
{
F(i,2,maxn-1) _log[i]=_log[i>>1]+1;
while (scanf("%s",s)!=EOF&&s[0]!='#')
{
ansl=ansr=0,mx=0;minn=inf;
printf("Case %d: ",++kas);
mx=0;
n=strlen(s);
F(i,0,n-1)
{
SA.s[i]=s[i]-'a'+1;
SB.s[i]=s[n-i-1]-'a'+1;
minn=min(minn,(int)s[i]);
}
SA.s[n]=SB.s[n]=0;
SA.build(n,30); SB.build(n,30);
for (int i=1;i<=n;++i) solve(i);
if (mx==0) printf("%c\n",minn);
else
{
F(i,ansl,ansr) printf("%c",s[i]);
printf("\n");
}
}
}

  

POJ 3693 Maximum repetition substring ——后缀数组的更多相关文章

  1. poj 3693 Maximum repetition substring (后缀数组)

    其实是论文题.. 题意:求一个字符串中,能由单位串repeat得到的子串中,单位串重复次数最多的子串.若有多个重复次数相同的,输出字典序最小的那个. 解题思路:其实跟论文差不多,我看了很久没看懂,后来 ...

  2. POJ 3693 Maximum repetition substring (后缀数组+RMQ)

    题意:给定一个字符串,求其中一个由循环子串构成且循环次数最多的一个子串,有多个就输出最小字典序的. 析:枚举循环串的长度ll,然后如果它出现了两次,那么它一定会覆盖s[0],s[ll],s[ll*2] ...

  3. POJ3693 Maximum repetition substring 后缀数组

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

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

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

  5. POJ 3693 Maximum repetition substring(最多重复次数的子串)

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

  6. Maximum repetition substring 后缀数组

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

  7. POJ3693 Maximum repetition substring —— 后缀数组 重复次数最多的连续重复子串

    题目链接:https://vjudge.net/problem/POJ-3693 Maximum repetition substring Time Limit: 1000MS   Memory Li ...

  8. POJ 3693 Maximum repetition substring(后缀数组)

    Description The repetition number of a string is defined as the maximum number R such that the strin ...

  9. POJ 3693 Maximum repetition substring(后缀数组+ST表)

    [题目链接] poj.org/problem?id=3693 [题目大意] 求一个串重复次数最多的连续重复子串并输出,要求字典序最小. [题解] 考虑错位匹配,设重复部分长度为l,记s[i]和s[i+ ...

随机推荐

  1. Android中的ListView属性使用总结

    Android中使用ListView控件比较常见,如果能知道常用的一些属性使用,肯定会少很多坑. 1.ListView是常用的显示控件,默认背景是和系统窗口一样的透明色,如果给ListView加上背景 ...

  2. 从Assets读取文件 用scanner扫描inputstream

    代码如下: 对InputStream的处理,从assets获取数据 InputStream in; try { in = getAssets().open("Android05.txt&qu ...

  3. Android笔记--Bitmap

    Android | Bitmap解析 Android中Bitmap是对图像的一种抽象.通过他可以对相应的图像进行剪裁,旋转,压缩,缩放等操作.这里循序渐进的一步步了解Bitmap的相关内容. 先了解B ...

  4. uvm_pkg——老板,打包带走

    Thus spake the master programmer: “After three day without programming, life becomes meaningless.” 编 ...

  5. springMVC 中 ajax get 请求和 post 请求的坑以及参数传递

    1, ajax 请求 无论为 post ,或者 get ,url中带有?形式的参数,后台都能以String类型变量接收,变量名称和参数名称必须一致 前台ajax: $.ajax( "prod ...

  6. License开源许可协议

    开源许可协议 License是软件的授权许可,表述了你获得代码后拥有的权利,可以对别人的作品进行何种操作,何种操作又是被禁止的. 开源许可证种类 Open Source Initiative http ...

  7. 迅为4412开发板Linux设备树的镜像烧写和源码简单优化教程

    1 烧写:   烧写和4412默认镜像的烧写类似,使用fastboot. 先更新uboot,用4412默认uboot更新支持设备树的uboot 用支持设备树的uboot烧写. 进入支持设备树的uboo ...

  8. MIPS—冒泡排序

    SORT 使用冒泡排序对整数数组进行排序,这种排序虽然不是最快的,但却是最简单的. C语言代码 #include<stdio.h> #include<iostream> usi ...

  9. 利用python进行数据分析1_numpy的基本操作,建模基础

    import numpy as np # 生成指定维度的随机多维数据 data=np.random.rand(2,3) print(data) print(type(data)) 结果: [[0.11 ...

  10. 一张图看懂苹果MacBook所有屏幕分辨率

    苹果全新12寸超薄MacBook比曾经最薄的MacBook Air更薄,不过却配备了Retina视网膜显示屏.12英寸RetinaMacBook上的显示屏分辨率为2304*1440,虽然不如15寸和1 ...