【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 ...
随机推荐
- 增强的格式化字符串format函数
http://blog.csdn.net/handsomekang/article/details/9183303 自python2.6开始,新增了一种格式化字符串的函数str.format(),可谓 ...
- Node第二天
一.http模块: 步骤一:创建http服务器 const https = require('https'); 步骤二:const fs = require('fs'); 步骤三:创建请求=> ...
- 【mysql】 数据库字符集和排序规则
库的字符集影响表和字段的字符集 数据库字符集 >表的字符集 > 字段的字符集 (从前往后优先级由低到高,从左往右继承,如果表没设置字符集,继承数据库的,如果字段没设置,继承表的) 数据库的 ...
- 删除项目开发中的.pyc文件
在实际开发中python会自动生成很多pyc文件,但是这些pyc文件是不需要我们追踪的,删除了对项目也没有影响,下面是删除pyc文件的方法. Linux或Mac系统 find /tmp -name & ...
- Windows下安装配置SQLite和使用的教程
什么是SQLite SQLite是一款非常轻量级的关系数据库系统,支持多数SQL92标准.SQLite在使用前不需要安装设置,不需要进程来启动.停止或配置,而其他大多数SQL数据库引擎是作为一个单独的 ...
- 数论:HDU1066-Last non-zero Digit in N!
题目: Last non-zero Digit in N! Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K ...
- [USACO]玉米实验(单调队列)
Description 约翰决定培育新的玉米品种以提高奶牛的产奶效率.约翰所有的土地被分成 N ×N 块,其中第 r行第 c 列的玉米质量为 Ar,c.他打算找一块质量比较均匀的土地开始自己的实验.经 ...
- secureCRT中vim行号下划线问题
在vim中发现开启显示行号(set number)或语法高亮(syntax on)时,发现文档中很多地方都有下划线,对视觉产生极大干扰.开始还以为是vim的某个配置造成的,后来发现真正的元凶是secu ...
- django的as_view方法实现分析
django的类视图拥有自动查找指定方法的功能, 通过调用是通过as_view()方法实现 urls.py from meduo_mall.demo import views urlpatterns ...
- complex类的定义、实现
复数类complex的定义.实现(求模.复数加法) #include <iostream> #include <cmath> using namespace std; clas ...