题解 SP687 【REPEATS - Repeats】
考虑可以枚举字符串上的两个点,求出两个点所对应后缀的\(LCP\)和所对应前缀的\(LCS\),两点之间的距离为\(len\),则这两个点对答案的贡献为:
\]
取最大值即为答案,可以通过下图来理解这个式子:

首先已经将字符串分为了若干个长度为\(len\)的块,箭头指向的位置为枚举的两个点,蓝色部分为\(LCS\),红色部分为\(LCP\),\(LCS+LCP+L-1\)即为黄色直线框起来的部分,不难发现,通过这样枚举点对,我们肯定能在其中一次枚举中找到重复次数最多的连续重复子串的重复次数。
枚举点对时可以枚举长度\(len\),这样枚举复杂度就是\(O(n\ \log\ n)\)的了,求\(LCP\)和\(LCS\)用后缀数组实现即可。
\(code:\)
#include<bits/stdc++.h>
#define maxn 200010
using namespace std;
template<typename T> inline void read(T &x)
{
x=0;char c=getchar();bool flag=false;
while(!isdigit(c)){if(c=='-')flag=true;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
if(flag)x=-x;
}
int T,n,ans;
struct node
{
int n,m;
int b[maxn],rk[maxn],sa[maxn],tp[maxn],ht[maxn];
int lg[maxn],f[maxn][25];
char s[maxn];
void rsort()
{
for(int i=0;i<=m;++i) b[i]=0;
for(int i=1;i<=n;++i) b[rk[i]]++;
for(int i=1;i<=m;++i) b[i]+=b[i-1];
for(int i=n;i;--i) sa[b[rk[tp[i]]]--]=tp[i];
}
void SA()
{
for(int i=1;i<=n;++i) rk[i]=s[i],tp[i]=i;
rsort();
for(int k=1;k<=n;k<<=1)
{
int num=0;
for(int i=n-k+1;i<=n;++i) tp[++num]=i;
for(int i=1;i<=n;++i)
if(sa[i]>k)
tp[++num]=sa[i]-k;
rsort(),memcpy(tp,rk,sizeof(rk)),rk[sa[1]]=num=1;
for(int i=2;i<=n;++i)
rk[sa[i]]=(tp[sa[i]]==tp[sa[i-1]]&&tp[sa[i]+k]==tp[sa[i-1]+k])?num:++num;
if(num==n) break;
m=num;
}
int k=0;
for(int i=1;i<=n;++i) rk[sa[i]]=i;
for(int i=1;i<=n;++i)
{
if(rk[i]==1) continue;
if(k) k--;
int j=sa[rk[i]-1];
while(s[i+k]==s[j+k]) k++;
ht[rk[i]]=k;
}
}
void ST()
{
lg[0]=-1;
for(int i=1;i<=n;++i) lg[i]=lg[i>>1]+1;
for(int i=1;i<=n;++i) f[i][0]=ht[i];
for(int j=1;j<=20;++j)
for(int i=1;i+(1<<j)-1<=n;++i)
f[i][j]=min(f[i][j-1],f[i+(1<<(j-1))][j-1]);
}
int query(int l,int r)
{
l=rk[l],r=rk[r];
if(l>r) swap(l,r);
l++;
int len=lg[r-l+1];
return min(f[l][len],f[r-(1<<len)+1][len]);
}
void init()
{
m=150,SA(),ST();
}
}LCP,LCS;
int main()
{
read(T);
while(T--)
{
read(n),LCP.n=LCS.n=n,ans=0;
for(int i=1;i<=n;++i) cin>>LCP.s[i],LCS.s[n-i+1]=LCP.s[i];
LCP.init(),LCS.init();
for(int len=1;len<=n;++len)
for(int i=1;i+len<=n;i+=len)
ans=max(ans,(LCP.query(i,i+len)+LCS.query(n-i+1,n-i-len+1)+len-1)/len);
printf("%d\n",ans);
}
return 0;
}
题解 SP687 【REPEATS - Repeats】的更多相关文章
- SPOJ REPEATS Repeats (后缀数组 + RMQ:子串的最大循环节)题解
题意: 给定一个串\(s\),\(s\)必有一个最大循环节的连续子串\(ss\),问最大循环次数是多少 思路: 我们可以知道,如果一个长度为\(L\)的子串连续出现了两次及以上,那么必然会存在\(s[ ...
- SP687 REPEATS - Repeats
给定字符串,求重复次数最多的连续重复子串. 题目很简单,被细节坑惨了... 前置的一个推论:请看这里. #include <bits/stdc++.h> using namespace s ...
- SP687 REPEATS - Repeats(后缀数组)
一个初步的想法是我们枚举重复子串的长度\(L\).然后跑一遍SA.然后我们枚举一个点\(i\),令他的对应点为\(i+L\),然后求出这两个点的LCP和LCS的长度答案就是这个点的答案就是\((len ...
- SPOJ - REPEATS Repeats (后缀数组)
A string s is called an (k,l)-repeat if s is obtained by concatenating k>=1 times some seed strin ...
- spoj687 REPEATS - Repeats (后缀数组+rmq)
A string s is called an (k,l)-repeat if s is obtained by concatenating k>=1 times some seed strin ...
- SPOJ 687 REPEATS - Repeats
题意 给定字符串,求重复次数最多的连续重复子串 思路 后缀数组的神题 让我对着题解想了快1天 首先考虑一个暴力,枚举循环串的长度l,然后再枚举每个点i,用i和i+l匹配,如果匹配长度是L,这个循环串就 ...
- SPOJ - REPEATS Repeats (后缀数组+RMQ)
题意:求一个串中出现重复子串次数最多的数目. 析:枚举每个长度的子串,至少要重复两次,必然会经过s[l*i]中相邻的两个,然后再分别向前和向后匹配即可. 代码如下: #pragma comment(l ...
- SPOJ - REPEATS —— 后缀数组 重复次数最多的连续重复子串
题目链接:https://vjudge.net/problem/SPOJ-REPEATS REPEATS - Repeats no tags A string s is called an (k,l ...
- SPOJ Repeats(后缀数组+RMQ-ST)
REPEATS - Repeats no tags A string s is called an (k,l)-repeat if s is obtained by concatenating k& ...
随机推荐
- .NETCore微服务探寻(二) - 认证与授权
前言 一直以来对于.NETCore微服务相关的技术栈都处于一个浅尝辄止的了解阶段,在现实工作中也对于微服务也一直没有使用的业务环境,所以一直也没有整合过一个完整的基于.NETCore技术栈的微服务项目 ...
- android异步任务asyncTask详细分析
android中的耗时操作需要放在子线程中去执行 asynctask是对Handler和和线程池的封装,直接使用比THread效率更加的高效因为封装了线程池,比我们每次直接new Thread效率更高 ...
- 一个工作了四年的java程序员的心得体会
年底了,该给自己写点总结了!从毕业到现在已经快4年啦,一直在Java的WEB开发行业混迹.我不是牛人,但是自我感觉还算是个合格的程序员,有必要写下自己将近4年来的经历,给自我以提示,给刚入行的朋友提供 ...
- 使用TimerTask创建定时任务
使用TimerTask创建定时任务,打包之后应用于linux系统 step1:创建java项目 step2:代码实现 定时任务实现类CreateTask.java是打印操作者的名字 配置准换类Conf ...
- HashMap的基本使用
常用方法 首先,我们应该知道HashMap类实现了Map接口,所以实现了Map常用的一些方法. (1) 插入键值对数据 public V put(K key, V value) (2)根据键值获取键值 ...
- [区间+线性dp]数字游戏
题目描述 丁丁最近沉迷于一个数字游戏之中.这个游戏看似简单,但丁丁在研究了许多天之后却发觉原来在简单的规则下想要赢得这个游戏并不那么容易.游戏是这样的,在你面前有一圈整数(一共\(n\)个),你要按顺 ...
- AnalyticDB实现和特点浅析
目录 AnalyticDB介绍与背景 AnalyticDB详细解析 架构设计 数据分区 读写分离和读写流程 其他特性介绍 混合(列-行)存储引擎 索引 小结 本篇主要是根据AnalyticDB的论文, ...
- 三.cmdb
一.服务器管理: https://github.com/rfjer/autoAdmin/tree/master/apps/servers 一服务器信息收集方式: 1.物理服务器 跑脚本传(bash/a ...
- 【python爬虫实战】使用Selenium webdriver采集山东招考数据
目录 1.目标 2.Selenium webdriver说明 2.1 为什么使用webdriver 2.2 webdriver支持浏览器 2.3 配置与使用说明 3.采集 3.1 分析网站 3.2 遍 ...
- Windows系统VSCode、VBox搭建C/C++开发环境
好几年没有写过C/C++代码,基本上都忘光了,之前是使用VC++6.0写代码的,最近用VSCode成功搭建了C/C++开发环境,这里记录一下搭建过程. 1. 安装VSCode 在官网https://c ...