【BZOJ2320】最多重复子串

Description

一个字符串P的重复数定义为最大的整数R,使得P可以分为R段连续且相同的子串。比方说,“ababab”的重复数为3,“ababa”的重复数为1。

Your Task

对于给定的串S,找出S的一个子串K使得K的重复数最大。

Input

第一行T表示数据组数

对于每组数据,一行中一个仅包含小写字母的字符串S

Output

对于每组数据,在一行中输出K,如果有多个解,输出字典序最小的那一个

Sample Input

2
ccabababc
daabbccaa

Sample Output

ababab
aa

HINT

100%:T≤10,S的长度不超过100000

题解:居然能第二次遇到这种套路,真是不容易(第一次在股市的预测)。

如果重复数为1,则答案就是最小的字符,下面只考虑重复数不是1的情况。

回忆next数组的性质,一个串的最小循环节为n-next[n](如果有的话),而我们要枚举什么呢?我们枚举的就是0~n-next[n]以及next[n]~n的部分。

具体地,我们枚举循环节的长度为len,然后每隔len的长度设一个关键点,这样就保证了每个循环节都只包含一个关键点。然后我们对于每个关键点i,求出它和下一个关键点的最长公共前缀A和最长公共后缀B,用$\lfloor{A+B-1\over len}\rfloor+1$更新答案。

如何求字典序最小呢?因为极长重复串的个数是O(n)的(Claris说的。。。),所以暴力判断即可。

时间复杂度取决于如何求LCP和LCS,如果用hash+二分的话是$O(nlog^2n)$的。

#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
typedef unsigned long long ull;
const int maxn=100010;
int n,ans,ap,bp;
ull hs[maxn],bs[maxn];
char str[maxn];
inline ull hash(int a,int b) {return hs[b]-((!a)?0:hs[a-1]*bs[b-a+1]);}
inline int lcs(int a,int b)
{
int l=0,r=min(a,b)+2,mid;
while(l<r)
{
mid=(l+r)>>1;
if(hash(a-mid+1,a)==hash(b-mid+1,b)) l=mid+1;
else r=mid;
}
return l-1;
}
inline int lcp(int a,int b)
{
int l=0,r=n-max(a,b)+1,mid;
while(l<r)
{
mid=(l+r)>>1;
if(hash(a,a+mid-1)==hash(b,b+mid-1)) l=mid+1;
else r=mid;
}
return l-1;
}
void updata(int a,int b)
{
if(ap==-1) ap=a,bp=b;
else
{
int l1=b-a+1,l0=bp-ap+1,k=min(lcp(a,ap),min(l1,l0));
if((k<=l1?str[a+k]:0)<(k<=l0?str[ap+k]:0)) ap=a,bp=b;
}
}
inline void calc(int x)
{
for(int i=0,a,b,c;i+x<n;i+=x) if(str[i]==str[i+x])
{
a=lcs(i,i+x),b=lcp(i,i+x),c=(a+b-1)/x+1;
if(c>ans) ans=c,ap=bp=-1;
if(ans!=1&&c==ans) for(int j=i-a+1;j+c*x-1<=i+x+b-1;j++) updata(j,j+c*x-1);
}
}
void work()
{
scanf("%s",str),n=strlen(str),ans=1,ap=bp=-1;
int i;
for(bs[0]=1,i=1;i<=n;i++) bs[i]=bs[i-1]*131;
for(i=0;i<n;i++) hs[i]=((!i)?0:hs[i-1])*131+str[i],ap=(ap==-1||str[i]<str[ap])?i:ap,bp=ap;
for(i=1;i<=n&&n/i>=ans;i++) calc(i);
for(i=ap;i<=bp;i++) printf("%c",str[i]);
printf("\n");
}
int main()
{
int T; scanf("%d",&T);
while(T--) work();
return 0;
}//1 ababacac

【BZOJ2320】最多重复子串 调和级数+hash的更多相关文章

  1. BZOJ2320 : 最多重复子串

    本题就是求重复数最多的字典序最小的$runs$,如果重复数为1,那么做法显然,然后只考虑重复数大于1的情况. 从小到大枚举长度$len$,对于每个关键点$x=i\times len$,有且仅有一个长度 ...

  2. 【TOJ 2406】Power Strings(KMP找最多重复子串)

    描述 Given two strings a and b we define a*b to be their concatenation. For example, if a = "abc& ...

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

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

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

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

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

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

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

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

  7. POJ-3693/HDU-2459 Maximum repetition substring 最多重复次数的子串(需要输出具体子串,按字典序)

    http://acm.hdu.edu.cn/showproblem.php?pid=2459 之前hihocoder那题可以算出最多重复次数,但是没有输出子串.一开始以为只要基于那个,每次更新答案的时 ...

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

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

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

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

随机推荐

  1. Node.js meitulu图片批量下载爬虫1.02版

    以前版本需要先查看网页源码,然后肉眼找到图片数量和子目录,虽说不费事,但多少有点不方便. 于是修改了一下,用cheerio自己去找找到图片数量和子目录,只要修改页面地址就行了.至此社会又前进了一步. ...

  2. 动态创建的文本框想要加上jQuery的datepicker功能变成日期选择控件该怎么办?

    通常页面输入控件想得到日期选择功能,借助jQuery是这样实现的: 1.载入css和js <script src="jqueryui/jquery-ui.js" type=& ...

  3. 用C++实现文件压缩(1.5)

    今天主要做的就是,将完成huffman编码的数据以二进制的形式写入文件中.这是个挺苦逼的活. 不过好在我以前玩过一段时间的单片机,所有能够较好的实现位运算,一位一位的将数据存放到缓冲区中,然后统一写入 ...

  4. iOS-仿支付宝加载web网页添加进度条

    代码地址如下:http://www.demodashi.com/demo/11727.html 目前市场上APP常会嵌入不少的h5页面,参照支付宝显示web页面的方式, 做了一个导航栏下的加载进度条. ...

  5. 关于继承Fragment后重写构造方法而产生的错误

    在android开发中.写了一个关于继承Fragment的类时,假设有重载构造函数时.会提示"Avoid non-default constructors in fragments: use ...

  6. C# 匿名类型 分组 求和

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  7. Java获取网卡的mac地址

    为了项目的安全,有时候需要得到电脑的唯一码,比如:网卡的mac地址.和大家分享一下,下面是项目中用到的工具类: import java.io.BufferedReader;import java.io ...

  8. sqrt函数实现(神奇的算法)

    我们平时经常会有一些数据运算的操作,需要调用sqrt,exp,abs等函数,那么时候你有没有想过:这个些函数系统是如何实现的?就拿最常用的sqrt函数来说吧,系统怎么来实现这个经常调用的函数呢? 虽然 ...

  9. Redis 哈希槽

    Redis 集群中内置了 16384 个哈希槽,当需要在 Redis 集群中放置一个 key-value时,redis 先对 key 使用 crc16 算法算出一个结果,然后把结果对 16384 求余 ...

  10. crontab 解析

    一.crontab简介 Linux 提供了一个非常强大且易用的设置周期性执行指令的工具命令--crontab,常常用于设置循环任务的执行. 默认情况下,任何使用者若不被加入/etc/cron.deny ...