poj3294
首先后缀数组预处理
然后二分答案len很显然,然后考虑怎么判定
我们用左右指针顺着名次扫描一下,初始左右指针为1
根据LCP(i,j)=min(height[rank[i]+1]~height[rank[j]]) 设rank[i]<rank[j]
移动右指针扫描得到一组后缀[i,j]之间LCP>=len,h[j+1]<len
然后判断一下这组后缀是否有超过半数的原串,如果满足则记录
然后左右指针都从j+1开始
由于每个后缀最多被扫描一次判断一次,所以必然O(n)
注意多个串相连接的时候要用不同的字符作为分隔符
var ans,x,y,sa,sum,rank,h,loc:array[..] of longint;
v:array[..] of boolean;
j,len,l,r,k,i,n,m,p,tot:longint;
s,ch:ansistring; procedure suffix;
begin
fillchar(sum,sizeof(sum),);
for i:= to n do
begin
y[i]:=ord(s[i]);
inc(sum[y[i]]);
end;
m:=;
for i:= to m do
sum[i]:=sum[i-]+sum[i];
for i:=n downto do
begin
sa[sum[y[i]]]:=i;
dec(sum[y[i]]);
end;
p:=;
rank[sa[]]:=;
for i:= to n do
begin
if (y[sa[i]]<>y[sa[i-]]) then inc(p);
rank[sa[i]]:=p;
end;
m:=p;
j:=;
while m<n do
begin
fillchar(sum,sizeof(sum),);
y:=rank;
p:=;
for i:=n-j+ to n do
begin
inc(p);
x[p]:=i;
end;
for i:= to n do
if sa[i]>j then
begin
inc(p);
x[p]:=sa[i]-j;
end; for i:= to n do
begin
rank[i]:=y[x[i]];
inc(sum[rank[i]]);
end;
for i:= to m do
inc(sum[i],sum[i-]);
for i:=n downto do
begin
sa[sum[rank[i]]]:=x[i];
dec(sum[rank[i]]);
end;
p:=;
rank[sa[]]:=;
for i:= to n do
begin
if (y[sa[i]]<>y[sa[i-]]) or (y[sa[i]+j]<>y[sa[i-]+j]) then inc(p);
rank[sa[i]]:=p;
end;
m:=p;
j:=j shl ;
end;
h[]:=;
p:=;
for i:= to n do
begin
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;
if p> then dec(p);
end;
end; function solve(l,r:longint):boolean;
var i,t:longint;
begin
fillchar(v,sizeof(v),false);
t:=;
for i:=l to r do
if (loc[sa[i]]<>-) then
if not v[loc[sa[i]]] then
begin
inc(t);
v[loc[sa[i]]]:=true;
end;
if t>k shr then exit(true) else exit(false);
end; function check(len:longint):boolean;
var b,e,i:longint;
fl:boolean; begin
fl:=false;
b:=;
e:=;
for i:= to n do
begin
if h[i]>=len then inc(e)
else begin
if solve(b,e) then
begin
if not fl then tot:=;
fl:=true;
inc(tot);
ans[tot]:=sa[b];
end;
b:=i;
e:=i;
end;
end;
if b<e then //注意收尾
begin
if solve(b,e) then
begin
if not fl then tot:=;
inc(tot);
fl:=true;
ans[tot]:=sa[b];
end;
end;
exit(fl);
end; begin
readln(k);
while k<> do
begin
s:='';
r:=;
m:=;
for i:= to k do
begin
readln(ch);
if r<length(ch) then r:=length(ch);
for j:= to length(ch) do
begin
inc(m);
loc[m]:=i;
end;
inc(m);
loc[m]:=-;
s:=s+ch+chr(i);
end;
n:=length(s);
suffix;
l:=;
len:=;
while l<=r do
begin
m:=(l+r) shr ;
if check(m) then
begin
len:=m;
l:=m+;
end
else r:=m-;
end;
if k= then
begin
writeln(s);
writeln;
end
else if len= then
begin
writeln('?');
writeln;
end
else begin
for i:= to tot do
begin;
for j:=ans[i] to ans[i]+len- do
write(s[j]);
writeln;
end;
writeln;
end;
readln(k);
end;
end.
poj3294的更多相关文章
- 【POJ3294】 Life Forms (后缀数组+二分)
Life Forms Description You may have wondered why most extraterrestrial life forms resemble humans, d ...
- 【poj3294】 Life Forms
http://poj.org/problem?id=3294 (题目链接) 题意 给定 n 个字符串,求出现在不小于 k 个字符串中的最长子串. Solution 后缀数组论文题.. 将 n 个字符串 ...
- POJ3294 Life Forms —— 后缀数组 最长公共子串
题目链接:https://vjudge.net/problem/POJ-3294 Life Forms Time Limit: 5000MS Memory Limit: 65536K Total ...
- 【POJ3294】Life Forms(后缀数组,二分)
题意: n<=100 len[i]<=1000 思路:这是一道论文题 ..]of longint; ch:..]of ansistring; n,n1,l,r,mid,last,i,j,m ...
- poj3294 出现次数大于n/2 的公共子串
Life Forms Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 13063 Accepted: 3670 Descr ...
- POJ3294 Life Forms(后缀数组)
引用罗穗骞论文中的话: 将n 个字符串连起来,中间用不相同的且没有出现在字符串中的字符隔开,求后缀数组.然后二分答案,用和例3 同样的方法将后缀分成若干组,判断每组的后缀是否出现在不小于k 个的原串中 ...
- poj3294 Life Forms(后缀数组)
[题目链接] http://poj.org/problem?id=3294 [题意] 多个字符串求出现超过R次的最长公共子串. [思路] 二分+划分height,判定一个组中是否包含不小于R个不同字符 ...
- poj3294 --Life Forms
Life Forms Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 12483 Accepted: 3501 Descr ...
- Life Forms (poj3294 后缀数组求 不小于k个字符串中的最长子串)
(累了,这题做了很久!) Life Forms Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 8683 Accepted ...
随机推荐
- bash登录式shell(完全切换)与非登陆式shell(不完全切换)区别
1.以登录式shell切换用户 su - username 登录式shell读取配置文件及其顺序: /etc/profile /etc/profile.d/*.sh ~/.bash_profile ~ ...
- Spring中 bean定义的parent属性机制的实现分析
在XML中配置bean元素的时候,我们常常要用到parent属性,这个用起来很方便就可以让一个bean获得parent的所有属性 在spring中,这种机制是如何实现的? 对于这种情况 tra ...
- VS2010打不开VS2012 .NET MVC 工程,及打开后部分模块加载不正确的解决办法
转自http://www.xuebuyuan.com/2042634.html 首先,如果sln打开不正确,用(notepad++)打开sln 比如 VS2010的前两行为: Microsoft Vi ...
- Oracle Application Express (APEX 4.2) 中进行ajax调用
Oracle Application Express 4.2 (APEX 4.2)是一个快捷的web应用开发工具.在开发网页的过程中有时候会用到ajax请求. 建立ajax请求的方式: 1.建立后台的 ...
- SQL2005 学习笔记 窗口函数(OVER)【转】
1.简介: SQL Server 2005中的窗口函数帮助你迅速查看不同级别的聚合,通过它可以非常方便地累计总数.移动平均值.以及执行其它计算. 窗口函数功能非常强大,使用起来也十分容易.可以使用这个 ...
- winform程序中界面的跳转问题
首先是我们进行窗口间的跳转,尤其注意的是winform程序里面的空间都是中线程安全的.但是注意的是如果你在一个线程中操纵另外的控件,这时候会提示你一个错误,这个错误的解决方法准备单独的在另一篇文章中来 ...
- C++专题 - 修练8年C++面向对象程序设计之体会 林锐
六年前,我刚热恋“面向对象”(Object-Oriented)时,一口气记住了近十个定义.六年后,我从几十万行程序中滚爬出来准备写点心得体会时, 却无法解释什么是“面向对象”,就象说不清楚什么是数学那 ...
- QuickSort 递归 分治
QuickSort 参考<算法导论>,<C程序设计语言> #include<stdio.h> void swap(int v[], int i, int j); v ...
- 寒假的ACM训练三(PC110107/UVa10196)
#include <iostream> #include <string.h> using namespace std; char qp[10][10]; int result ...
- 关于MVC中使用dynamic
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAA2kAAAB6CAIAAACqQIxZAAAgAElEQVR4nO2dT2wcx53v6zgXAgsYvA