【POJ3693】Maximum repetition substring (SA)
这是一道神奇的题目..论文里面说得不清楚,其实是这样...如果一个长度为l的串重复多次,那么至少s[1],s[l+1],s[2*l+1],..之中有相邻2个相等...设这时为j=i*l+1,k=j+l,我们这时候借助SA和RMQ O(1)求出:m=lcp(j,k),这时候,重复次数至少ans=m div l+1 。 当然,我们枚举到不一定能够是最优啊,因为你枚举的不一定是字符串的首尾..那这时候怎么办?就是论文里面说的,向前和向后匹配。我们设t=l-m mod l..可以理解为,这时候 m mod l为多出来的字符,t就看成是前面少的字符个数..当然如果m mod l=0就不用管这个了...那也就是说,我们再判断是否lcp(j-t,k-t)>=l 如果成立,那么 ans++ ...因为可以多出一段..
上面就解决了求最长的问题,下面将关于字典序的这个...其实SA就是字典序了,只要枚举是否 lcp(sa[i],sa[i]+l)>=(ans-1)*l,若成立,显然当前sa[i]起始长度为l的字符串就是答案...
嗯..写完顿时觉得涨姿势了..
const maxn=;
var
rec,c,h,rank,sa,x,y:array[..maxn] of longint;
f:array[..maxn,..] of longint;
n,cas:longint;
s:ansistring; function max(x,y:longint):longint; begin if x>y then exit(x) else exit(y); end;
function min(x,y:longint):longint; begin if x<y then exit(x) else exit(y); end;
procedure swap(var x,y:longint); var tmp:longint; begin tmp:=x;x:=y;y:=tmp; end; procedure make;
var p,i,tot:longint;
begin
p:=;
while p<n do
begin
fillchar(c,sizeof(c),);
for i:= to n-p do y[i]:=rank[i+p];
for i:= n-p+ to n do y[i]:=;
for i:= to n do inc(c[y[i]]);
for i:= to n do inc(c[i],c[i-]);
for i:= to n do
begin
sa[c[y[i]]]:=i;
dec(c[y[i]]);
end;
fillchar(c,sizeof(c),);
for i:= to n do x[i]:=rank[i];
for i:= to n do inc(c[x[i]]);
for i:= to n do inc(c[i],c[i-]);
for i:= n downto do
begin
y[sa[i]]:=c[x[sa[i]]];
dec(c[x[sa[i]]]);
end;
for i:= to n do sa[y[i]]:=i;
tot:=;
rank[sa[]]:=;
for i:= to n do
begin
if (x[sa[i]]<>x[sa[i-]]) or (x[sa[i]+p]<>x[sa[i-]+p]) then inc(tot);
rank[sa[i]]:=tot;
end;
p:=p<<;
end;
for i:= to n do sa[rank[i]]:=i;
end; procedure makeh;
var i,j,p:longint;
begin
h[]:=; p:=;
for i:= to n do
begin
p:=max(p-,);
if rank[i]= then continue;
j:=sa[rank[i]-];
while (i+p<=n) and (j+p<=n) and (s[i+p]=s[j+p]) do inc(p);
h[rank[i]]:=p;
end;
end; procedure rmq;
var i,j:longint;
begin
for i:= to n do f[i,]:=h[i];
for i:= to trunc(ln(n)/ln()) do
for j:= to n-<<i+ do
f[j,i]:=min(f[j,i-],f[j+<<(i-),i-]);
end; procedure init;
var i,tot:longint;
begin
n:=length(s);
for i:= to n do x[i]:=ord(s[i]);
fillchar(c,sizeof(c),);
for i:= to n do inc(c[x[i]]);
for i:= to do inc(c[i],c[i-]);
for i:= to n do
begin
sa[c[x[i]]]:=i;
dec(c[x[i]]);
end;
rank[sa[]]:=;
tot:=;
for i:= to n do
begin
if x[sa[i]]<>x[sa[i-]] then inc(tot);
rank[sa[i]]:=tot;
end;
make;
makeh;
rmq;
end; function lcp(x,y:longint):longint;
var t:longint;
begin
x:=rank[x]; y:=rank[y];
if x>y then swap(x,y);
if x<y then inc(x);
t:=trunc(ln(y-x+)/ln());
exit(min(f[x,t],f[y-<<t+,t]));
end; procedure solve;
var m,l,i,j,tmp,t,ans,cnt:longint;
pd:boolean;
begin
init;
fillchar(rec,sizeof(rec),);
ans:=;
for l:= to n- do
begin
i:=;
while i+l<=n do
begin
m:=lcp(i,i+l);
tmp:=m div l+;
t:=l-m mod l;
t:=i-t;
if (t>) and (m mod l<>) and (lcp(t,t+l)>=m) then inc(tmp);
if tmp>ans then
begin
cnt:=;
rec[]:=l;
ans:=tmp;
end;
if cnt=ans then
begin
inc(cnt);
rec[cnt]:=l;
end;
i:=i+l;
end;
end;
pd:=false;
for i:= to n do
if not pd then
for j:= to cnt do
begin
l:=rec[j];
if lcp(sa[i],sa[i]+l)>=(ans-)*l then
begin
t:=sa[i];
l:=l*ans;
pd:=true;
break;
end;
end
else break;
inc(cas);
write('Case ',cas,': ');
for i:= t to t+l- do write(s[i]);
writeln;
end; Begin
cas:=;
readln(s);
while s[]<>'#' do
begin
solve;
readln(s);
end;
End.
【POJ3693】Maximum repetition substring (SA)的更多相关文章
- 【poj3693】Maximum repetition substring(后缀数组+RMQ)
题意:给定一个字符串,求重复次数最多的连续重复子串. 传说中的后缀数组神题,蒟蒻真的调了很久才对啊.感觉对后缀数组和RMQ的模版都不是很熟,导致还是会有很多各种各样的小错误= = 首先,枚举重复子串的 ...
- 【poj3693】 Maximum repetition substring
http://poj.org/problem?id=3693 (题目链接) 题意 给定一个字符串,求重复次数最多的连续重复子串,若存在多组解,输出字典序最小的. Solution 后缀数组论文题,就是 ...
- 【Poj-3693】Maximum repetition substring 后缀数组 连续重复子串
POJ - 3693 题意 SPOJ - REPEATS的进阶版,在这题的基础上输出字典序最小的重复字串. 思路 跟上题一样,先求出最长的重复次数,在求的过程中顺便纪录最多次数可能的长度. 因为sa数 ...
- 【SPOJ687&POJ3693】Maximum repetition substring(后缀数组)
题意: n<=1e5 思路: From http://hzwer.com/6152.html 往后匹配多远 r 用ST表求lcp即可...往前 l 就把串反过来再做一下.. 但是有可能求出来的最 ...
- 【po3693】Maximum repetition substring
题意: 给定一个字符串 求重复次数最多的连续重复子串 并输出字典序最小方案 题解: 枚举子串长度L 显然如果重复次数>1 那么答案串肯定包含s[1],s[1+L],s[1+L*2],...中的两 ...
- 【POJ 3693】Maximum repetition substring 重复次数最多的连续重复子串
后缀数组的论文里的例题,论文里的题解并没有看懂,,, 求一个重复次数最多的连续重复子串,又因为要找最靠前的,所以扫的时候记录最大的重复次数为$ans$,扫完后再后从头暴力扫到尾找重复次数为$ans$的 ...
- POJ-3693/HDU-2459 Maximum repetition substring 最多重复次数的子串(需要输出具体子串,按字典序)
http://acm.hdu.edu.cn/showproblem.php?pid=2459 之前hihocoder那题可以算出最多重复次数,但是没有输出子串.一开始以为只要基于那个,每次更新答案的时 ...
- POJ3693 Maximum repetition substring —— 后缀数组 重复次数最多的连续重复子串
题目链接:https://vjudge.net/problem/POJ-3693 Maximum repetition substring Time Limit: 1000MS Memory Li ...
- POJ3693 Maximum repetition substring [后缀数组 ST表]
Maximum repetition substring Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 9458 Acc ...
随机推荐
- pip 安装出现异常
MacBookPro:~ mac$ pip install numpy Collecting numpy Downloading numpy-1.13.1-cp35-cp35m-macosx_10_6 ...
- 多线程中使用HttpContext.Current为null的解决办法
HttpContext.Current.Server.MapPath(logFile) 这个是得到具体路径的方法 正常情况下是可以的 多线程情况下就为null 下边的代码原本的作用是把网站的异常 ...
- Bootstrap 历练实例-轮播(carousel)插件的事件
事件 下表列出了轮播(Carousel)插件中要用到的事件.这些事件可在函数中当钩子使用. 事件 描述 实例 slide.bs.carousel 当调用 slide 实例方法时立即触发该事件. $(' ...
- mbstring未安装
yum install php55w-mbstring.x86_64 把php版本换成自己的就ok
- C#冒泡排序程序
考虑到很多面试可能会考察冒泡排序的用法,所以特地花时间厘清了一下思路.下面说一下我的思路:冒泡排序核心就是比较方法,冒泡排序的比较方法顾名思义就是像气泡一样,最大(或者最小)的数往上冒.普通比较几个数 ...
- JAVA JDBC 连接 Oracle
使用 Junit 测试类编写 public class JdbcTest { private Connection con = null;// 创建一个数据库连接 private PreparedSt ...
- 【dp】奶牛家谱 Cow Pedigrees
令人窒息的奶牛题 题目描述 农民约翰准备购买一群新奶牛. 在这个新的奶牛群中, 每一个母亲奶牛都生两个小奶牛.这些奶牛间的关系可以用二叉树来表示.这些二叉树总共有N个节点(3 <= N < ...
- 爬虫学习(八)——带cookie的网页进行爬取
# 前提:# # 通常,很多网站需要登录才能进行浏览,所以在爬取这些网站时,也需要进行登录,并拿取登录时的cookie# # 登录网页,服务器会给客户端一个牌子cookie# # 访问登录页面时,带着 ...
- Redis常用诊断命令
1.info 命令查看redis信息,可以指定要查看的section名 sections:Server,clients,memory,persistence,stats,replication,cpu ...
- ajaxfileuplod 上传文件 essyui laoding 效果,防止重复上传文件
//放于上传前 function ajaxLoading(){ $("<div class=\"datagrid-mask\"></div>&qu ...