题意:给定一个串,长度<=10^5,求它重复次数最多的连续重复子串(输出字典序最小的那个)。

例如ccabcabc,答案就是abcabc

一开始没想清楚,结果调了好久。

原理:

按照L划分,因为相邻两个i之间隔着一个L,s[i*L]和s[(i+1)*L]必定是真正循环节的同一个位置。

对于当前的L,i,i+1,x=s[i*L],y=s[(i+1)*L],找前找后,知道了最早能匹配到t0,最晚能匹配到t1,因为不知道当前的起始点是真正循环节的第几个点,所以我们要往前找L个点看看它们是不是真正的起始点。

细节就看代码吧:

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
using namespace std; const int N=*;
int cl,rk[N],sa[N],Rs[N],y[N],wr[N],h[N],r[N][];
char c[N]; int minn(int x,int y){return x<y ? x:y;} void get_sa(int m)
{
for(int i=;i<=cl;i++) rk[i]=c[i]-'a'+;
for(int i=;i<=m;i++) Rs[i]=;
for(int i=;i<=cl;i++) Rs[rk[i]]++;
for(int i=;i<=m;i++) Rs[i]+=Rs[i-];
for(int i=cl;i>=;i--) sa[Rs[rk[i]]--]=i; int ln=,p=;
while(p<cl)
{
int k=;
for(int i=cl-ln+;i<=cl;i++) y[++k]=i;
for(int i=;i<=cl;i++) if(sa[i]>ln) y[++k]=sa[i]-ln; for(int i=;i<=cl;i++) wr[i]=rk[y[i]];
for(int i=;i<=m;i++) Rs[i]=;
for(int i=;i<=cl;i++) Rs[wr[i]]++;
for(int i=;i<=m;i++) Rs[i]+=Rs[i-];
for(int i=cl;i>=;i--) sa[Rs[wr[i]]--]=y[i]; for(int i=;i<=cl;i++) wr[i]=rk[i];
for(int i=cl+;i<=cl+ln;i++) wr[i]=;
p=;rk[sa[]]=;
for(int i=;i<=cl;i++)
{
if(wr[sa[i]]!=wr[sa[i-]] || wr[sa[i]+ln]!=wr[sa[i-]+ln]) p++;
rk[sa[i]]=p;
}
ln*=,m=p;
}
sa[]=,rk[]=;
} void get_h()
{
int k=,j;
for(int i=;i<=cl;i++) if(rk[i]!=)
{
j=sa[rk[i]-];
if(k) k--;
while(c[j+k]==c[i+k] && j+k<=cl && i+k<=cl) k++;
h[rk[i]]=k;
}
h[]=;
} void get_rmq()
{
for(int i=;i<=cl;i++) r[i][]=h[i];
for(int j=;(<<j)<=cl;j++)
for(int i=;i+(<<j)-<=cl;i++)
{
r[i][j]=minn(r[i][j-],r[i+(<<(j-))][j-]);
}
} int query_rmq(int i,int j)
{
if(i>j) swap(i,j);
i++;
int k=;
while(i+(<<(k+)) <= j) k++;
return minn(r[i][k],r[j-(<<k)+][k]);
} int main()
{
int x,y,z,t0,t1,now,ans,al,ar,T=;
while()
{
scanf("%s",c+);
cl=strlen(c+);
if(cl== && c[]=='#') return ;
printf("Case %d: ",++T);
get_sa();
get_h();
get_rmq();
ans=;al=ar=;
for(int L=;L*<=cl;L++)
{
for(int i=;L*(i+)+<=cl;i++)
{
x=L*i+,y=L*(i+)+;
if(c[x]!=c[y]) continue;
z=query_rmq(rk[x],rk[y]);
t1=y+z-;
t0=;
for(int j=;j<=L-;j++)//往前匹配
{
if(x-j< || c[x-j]!=c[y-j]) break;
t0=x-j;
now=((t1-t0+)/L);
if(now>ans || (now==ans && rk[t0]<rk[al])) ans=now,al=t0,ar=t0+now*L-;
}
}
}
if(ans==) printf("%c\n",c[sa[]]);
else
{
for(int i=al;i<=ar;i++) printf("%c",c[i]);printf("\n");
}
} return ;
}

【poj3693-重复次数最多的连续重复子串】后缀数组的更多相关文章

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

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

  2. 【POJ 3693】Maximum repetition substring 重复次数最多的连续重复子串

    后缀数组的论文里的例题,论文里的题解并没有看懂,,, 求一个重复次数最多的连续重复子串,又因为要找最靠前的,所以扫的时候记录最大的重复次数为$ans$,扫完后再后从头暴力扫到尾找重复次数为$ans$的 ...

  3. spoj687 后缀数组重复次数最多的连续重复子串

    REPEATS - Repeats no tags  A string s is called an (k,l)-repeat if s is obtained by concatenating k& ...

  4. POJ-3693-Maximum repetition substring(后缀数组-重复次数最多的连续重复子串)

    题意: 给出一个串,求重复次数最多的连续重复子串 分析: 比较容易理解的部分就是枚举长度为L,然后看长度为L的字符串最多连续出现几次. 既然长度为L的串重复出现,那么str[0],str[l],str ...

  5. poj 3693 后缀数组 重复次数最多的连续重复子串

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

  6. Repeats SPOJ - REPEATS(重复次数最多的连续重复子串)

    论文题例8 https://blog.csdn.net/queuelovestack/article/details/53031731这个解释很好 其实,当枚举的重复子串长度为i时,我们在枚举r[i* ...

  7. SPOJ - REPEATS —— 后缀数组 重复次数最多的连续重复子串

    题目链接:https://vjudge.net/problem/SPOJ-REPEATS REPEATS - Repeats no tags  A string s is called an (k,l ...

  8. POJ - 3693 Maximum repetition substring(重复次数最多的连续重复子串)

    传送门:POJ - 3693   题意:给你一个字符串,求重复次数最多的连续重复子串,如果有一样的,取字典序小的字符串. 题解: 比较容易理解的部分就是枚举长度为L,然后看长度为L的字符串最多连续出现 ...

  9. Maximum repetition substring (poj3693 后缀数组求重复次数最多的连续重复子串)

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

  10. Maximum repetition substring POJ - 3693(重复次数最多的连续重复子串)

    这题和SPOJ - REPEATS 一样  代码改一下就好了 这个题是求这个重复子串,还得保证字典序最小 巧妙运用sa 看这个 https://blog.csdn.net/queuelovestack ...

随机推荐

  1. 【多线程】 Task ,async ,await

    [多线程]Task ,async ,await 一. WinForm 里经常会用到多线程, 多线程的好出就不多说了,来说说多线程比较麻烦的地方 1. UI 线程与其他线程的同步,主要是 Form 和 ...

  2. iOS-读写plist文件

    读写plist文件 问题,我有一个plist文件,表示56个民族的,但是里面保存的字典,我想转换成一个数组 好的,那么就先遍历这个plist,然后将结果保存到一个数组中,这里出现的一个问题就是C语言字 ...

  3. Python 3基础教程26-多行打印

    本文来介绍多行打印.多行打印一般出现在欢迎界面,例如你玩过的游戏,第一个界面,很多文字显示. 我们随便打印几行,来模拟下这种多行打印情况. # 多行打印 print(''' 第一行内容 第二行内容 第 ...

  4. DCGAN: "Unsupervised Representation Learning with Deep Convolutional Generative Adversarial Network" Notes

    - Alec Radford, ICLR2016 原文:https://arxiv.org/abs/1511.06434 论文翻译:https://www.cnblogs.com/lyrichu/p/ ...

  5. CentOS 6.5 下安装redis

    1.登录虚拟机后,直接输入命令:yum -y install redis 会出现一个错误: 是因为少了epel源, 2.运行:yum -y install epel-release 最后出现 Comp ...

  6. winform自动最大化(在不同分辨率情况下)

    load函数末尾加: System.Drawing.Rectangle rec = Screen.GetWorkingArea(this); int SH = rec.Height; int SW = ...

  7. 集显也能硬件编码:Intel SDK && 各种音视频编解码学习详解

    http://blog.sina.com.cn/s/blog_4155bb1d0100soq9.html INTEL MEDIA SDK是INTEL推出的基于其内建显示核心的编解码技术,我们在播放高清 ...

  8. Ubuntu如何进入命令模式

    Ctrl+Alt+T 或者Ctrl+Alt+F2~F6进入命命令模式 Ctrl+Alt+F7返回桌面

  9. HTML精确定位之位置参数乱炖一锅

    一.前言 公司项目,需要在一个图片的右上角放置一个类似“X”的东西(其实是需要显示一个数字,就像微信一样,在右上角显示几个消息),然后需要用到html的定位,看了几个网上的例子,恍惚间看到了一个off ...

  10. ASP.NET页面之间传值Cookie(3)

    这个也是大家常使用的方法,Cookie用于在用户浏览器上存储小块的信息,保存用户的相关信息,比如用户访问某网站时用户的ID,用户的偏好等, 用户下次访问就可以通过检索获得以前的信息.所以Cookie也 ...