题意:给定一个字符串,求重复次数最多的连续重复子串。
  

  传说中的后缀数组神题,蒟蒻真的调了很久才对啊。感觉对后缀数组和RMQ的模版都不是很熟,导致还是会有很多各种各样的小错误= =

  首先,枚举重复子串的循环节为L,因为枚举的是循环节长度,所以是没有单调性的,那么枚举就要用0(n)的时间了。连续一次的情况是可以的,所以这里只考虑重复两次或以上的情况。

  记这个连续重复子串为L,我们可以发现,这个字符串一定会覆盖s[0],s[L],s[L*2].....这些点中相邻的两个(因为长度至少为2L嘛)。假设它覆盖的是s[L*i]和s[L*(i+1)],那么我们就往前和往后计算能匹配多远(往后匹配用到了后缀数组的height数组,往前匹配可以while到s[L*(i-1)],越过s[L*(i-1)]的情况和前面计算的重复了,可以不算)

  记往前匹配和往后匹配的最长长度为k,则重复次数为k/L+1。(如图)

  穷举长度L的时间为n,每次计算的时间为n/L。

  另外,要在较快的时间内求出以i为开头的后缀和以j为开头的后缀的最长公共前缀要用到RMQ。即快速算出min(height[rank[i]]~height[rank[j]])。用rmq[i][j]表示i~i+(1<<j)-1的min(height),具体如下。

代码如下:

 #include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define Maxn 100100 char s[Maxn];
int a[Maxn],n;
int rank[Maxn],sa[Maxn],Rsort[Maxn],y[Maxn],wr[Maxn];
int height[Maxn],d[Maxn][],ans[Maxn],as[Maxn],al;
int maxx,pos,len; int mymin(int xx,int yy) {return xx<yy?xx:yy;} void get_sa(int m)
{
memcpy(rank,a,sizeof(rank));
for(int i=;i<=m;i++) Rsort[i]=;
for(int i=;i<=n;i++) Rsort[rank[i]]++;
for(int i=;i<=m;i++) Rsort[i]+=Rsort[i-];
for(int i=n;i>=;i--) sa[Rsort[rank[i]]--]=i; int ln=,p=;
while(p<n)
{
int k=;
for(int i=n-ln+;i<=n;i++) y[++k]=i;
for(int i=;i<=n;i++) if(sa[i]>ln) y[++k]=sa[i]-ln;
for(int i=;i<=n;i++) wr[i]=rank[y[i]]; for(int i=;i<=m;i++) Rsort[i]=;
for(int i=;i<=n;i++) Rsort[wr[i]]++;
for(int i=;i<=m;i++) Rsort[i]+=Rsort[i-];
for(int i=n;i>=;i--) sa[Rsort[wr[i]]--]=y[i]; memcpy(wr,rank,sizeof(wr));
p=;rank[sa[]]=;
for(int i=;i<=n;i++)
{
if(wr[sa[i]]!=wr[sa[i-]]||wr[sa[i]+ln]!=wr[sa[i-]+ln]) p++;
rank[sa[i]]=p;
}
m=p,ln*=;
}
sa[]=rank[]=;
} void get_he()
{
int kk=;
for(int i=;i<=n;i++)
{
int j=sa[rank[i]-];
if(kk) kk--;
while(a[i+kk]==a[j+kk]) kk++;
height[rank[i]]=kk;
}
} void rmq_init()
{
for(int i=;i<=n;i++) d[i][]=height[i];
for(int j=;(<<j)<=n;j++)
for(int i=;i+(<<j)-<=n;i++)
d[i][j]=mymin(d[i][j-],d[i+(<<j-)][j-]);
} int rmq(int xx,int yy)
{
int t;
xx=rank[xx],yy=rank[yy];
if(xx>yy) t=xx,xx=yy,yy=t;
xx++;
int kk=;
while((<<(kk+))<=yy-xx+) kk++;
return mymin(d[xx][kk],d[yy-(<<kk)+][kk]);
} void ffind()
{
al=;
maxx=;
for(int i=;i<=n/;i++)
for(int j=;j+i<=n;j+=i)
{
if(a[j]!=a[j+i]) continue;
int kk=rmq(j,j+i),now,r;
now=kk/i+;r=i-kk%i;
//if(now>maxx) maxx=now,ans[al=1]=j,as[al]=i;
//else if(now==maxx) ans[++al]=j,as[al]=i;
int cnt=,p=j;
for(int m=j-;m>j-i&&a[m]==a[m+i]&&m;m--)
{
cnt++;
if(cnt==r) now++,p=m;
else p=rank[p]>rank[m]?m:p;
}
if(now>maxx) maxx=now,pos=p,len=i;
else if(now==maxx&&rank[pos]>rank[p]) pos=p,len=i;
}
} bool cp(int f1,int a1,int f2,int a2)
{
int kk=rmq(f1,f2);
if(kk>=a1-&&kk>=a2-) return a1<=a2?:;
if(kk>=a1-) return ;if(kk>=a2-) return ;
return a[f1+kk]>a[f2+kk];
} int main()
{
int kase=;
while()
{
scanf("%s",s+);
if(s[]=='#') break;
n=strlen(s+);int minn=;
memset(a,,sizeof(a));
for(int i=;i<=n;i++)
{
a[i]=s[i]-'a'+;
minn=mymin(minn,a[i]);
}
get_sa();
get_he();
rmq_init();
ffind();
printf("Case %d: ",++kase);
if(maxx==) printf("%c",minn+'a'-);
else
{
for(int i=pos;i<=pos+len*maxx-;i++) printf("%c",s[i]);
}
printf("\n");
}
return ;
}

poj3693

2015-12-15 17:02:11

【poj3693】Maximum repetition substring(后缀数组+RMQ)的更多相关文章

  1. poj3693 Maximum repetition substring (后缀数组+rmq)

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

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

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

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

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

  4. POJ3693 Maximum repetition substring 后缀数组

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

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

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

  6. Maximum repetition substring 后缀数组

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

  7. POJ 3693 Maximum repetition substring ——后缀数组

    重复次数最多的字串,我们可以枚举循环节的长度. 然后正反两次LCP,然后发现如果长度%L有剩余的情况时,答案是在一个区间内的. 所以需要找到区间内最小的rk值. 两个后缀数组,四个ST表,$\Thet ...

  8. 【Poj-3693】Maximum repetition substring 后缀数组 连续重复子串

    POJ - 3693 题意 SPOJ - REPEATS的进阶版,在这题的基础上输出字典序最小的重复字串. 思路 跟上题一样,先求出最长的重复次数,在求的过程中顺便纪录最多次数可能的长度. 因为sa数 ...

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

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

  10. poj3693 Maximum repetition substring

    题意 给出一个长度为\(n(n\leqslant 100000)\)的串,求一个字典序最小的子串使得它是某个字符串重复\(k\)次得到的,且\(k\)最大 题解 后缀数组论文上的题,跟上一篇uva那个 ...

随机推荐

  1. How to: cgminer (Bitcoin, Litecoin etc.) + AMD Radeon driver install on CentOS

    UPDATE 7/7/13: If you want to use Catalyst drivers version 12.8 you will find that X won’t start (er ...

  2. 幻灯片の纯CSS,NO JavaScript

    之前就遇到有人问,不用js,纯css实现幻灯片. 那么对于使用纯的css + html 怎样来实现幻灯片呢?下面有几种方法可供参考,有些还不成熟. 方案一:利用css3的animation 例子传送门 ...

  3. Win10 10586 更新

    最近发现,电脑c盘突然少了许多,发现c盘多了个windowsBT文件夹,大概6个G,恩,win10 又推出更新了,版本10586. 不知道为啥,更新时win10 把原来的下载的删除了,大概出了什么错误 ...

  4. Android线程与异步消息处理机制

    在程序开发时,对于一些比较耗时的操作,我们通常会为其开辟一个单独的线程来执行,这样可以尽可能的减少用户等待的时间.在Android中,默认情况下,所有的操作都是在主线程中进行的,这个主线程负责管理与U ...

  5. 关于sqlserver 2008 远程导入表数据

    /*不同服务器数据库之间的数据操作*/ --创建链接服务器 exec sp_addlinkedserver   'ITSV ', ' ', 'SQLOLEDB ', '远程服务器名或ip地址 ' ex ...

  6. Android应用不随手机屏幕旋转的方法

    在主配置文件里面.在需要设置的activity项后面加上 android:screenOrientation="portrait",这个activity就保持竖屏显示了:在每个ac ...

  7. Java中的static关键字解析(转自海子)__为什么main方法必须是static的,因为程序在执行main方法的时候没有创建任何对象,因此只有通过类名来访问。

    Java中的static关键字解析 static关键字是很多朋友在编写代码和阅读代码时碰到的比较难以理解的一个关键字,也是各大公司的面试官喜欢在面试时问到的知识点之一.下面就先讲述一下static关键 ...

  8. Objective-c单例模式详解

    转载自:http://www.jianshu.com/p/85618bcd4fee 单例模式出现以后,关于它的争执就一直存在.在开发项目中,有很多时候我们需要一个全局的对象,而且要保证全局有且仅有一份 ...

  9. MVC中Razor视图基本语法(1)

    Razor前面,必须要跟前面的有空隙,即空格(多谢一楼提醒,url里面确实不用空格,如果要在url里面只需要@(ViewBag.),加上括号就好了),之后的必须要连贯,否则加小括号 1,在页面中输出单 ...

  10. 基于smarty+medoo手搭php简单的框架

    1.首先看一下搭建好的smarty目录(箭头位置是后新建的文件夹,也是框架结构的最终目录结构) 2.首先在根目录下新建index.php文件即入口文件,内容如下 <?phprequire_onc ...