首先后缀数组预处理
然后二分答案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的更多相关文章

  1. 【POJ3294】 Life Forms (后缀数组+二分)

    Life Forms Description You may have wondered why most extraterrestrial life forms resemble humans, d ...

  2. 【poj3294】 Life Forms

    http://poj.org/problem?id=3294 (题目链接) 题意 给定 n 个字符串,求出现在不小于 k 个字符串中的最长子串. Solution 后缀数组论文题.. 将 n 个字符串 ...

  3. POJ3294 Life Forms —— 后缀数组 最长公共子串

    题目链接:https://vjudge.net/problem/POJ-3294 Life Forms Time Limit: 5000MS   Memory Limit: 65536K Total ...

  4. 【POJ3294】Life Forms(后缀数组,二分)

    题意: n<=100 len[i]<=1000 思路:这是一道论文题 ..]of longint; ch:..]of ansistring; n,n1,l,r,mid,last,i,j,m ...

  5. poj3294 出现次数大于n/2 的公共子串

    Life Forms Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 13063   Accepted: 3670 Descr ...

  6. POJ3294 Life Forms(后缀数组)

    引用罗穗骞论文中的话: 将n 个字符串连起来,中间用不相同的且没有出现在字符串中的字符隔开,求后缀数组.然后二分答案,用和例3 同样的方法将后缀分成若干组,判断每组的后缀是否出现在不小于k 个的原串中 ...

  7. poj3294 Life Forms(后缀数组)

    [题目链接] http://poj.org/problem?id=3294 [题意] 多个字符串求出现超过R次的最长公共子串. [思路] 二分+划分height,判定一个组中是否包含不小于R个不同字符 ...

  8. poj3294 --Life Forms

    Life Forms Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 12483   Accepted: 3501 Descr ...

  9. Life Forms (poj3294 后缀数组求 不小于k个字符串中的最长子串)

    (累了,这题做了很久!) Life Forms Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 8683   Accepted ...

随机推荐

  1. wiki 使用笔记

    Wiki 安装:Linux(Redhat EL5.3)下安装配置MediaWiki wiki配置: 配置文件:DefaultSettings.php  //权限等配置 左边导航条:/wiki/inde ...

  2. gulp 初体验

    1,全局安装 gulp npm install --global gulp 但是一直无法成功,后来才知被墙了,于是使用了如下命令,安装cnpm npm install -g cnpm --regist ...

  3. Java-Junit 的Hello world

    这里介绍junit 4的基本配置: <1>建立一个java project项目. <2>在src目录下面建一个包,com.sun.junit4,在包下面写一点文件T.java ...

  4. Js 命名空间注册方法

    MyApp = { namespace: function () { var a = arguments, o = null, i, j, d, rt; for (i = 0; i < a.le ...

  5. (转)VS自带工具:dumpbin的使用

    有时候我们想查看一个exe引用了哪些动态库,或者我们想看某个动态库包含哪些接口函数,这个时候可以使用dumpbin.exe工具: 1.输入Dumpbin -imports calldll.exe查看它 ...

  6. linux ssh rsa免输入密码

    A为本地主机(即用于控制其他主机的机器) ; B为远程主机(即被控制的机器Server), 假如ip为172.24.253.2 ;     在A上的命令: ssh-keygen -t rsa (连续三 ...

  7. 创建Java线程池

    线程池的作用: 线程池作用就是限制系统中执行线程的数量. 根据系统的环境情况,可以自动或手动设置线程数量,达到运行的最佳效果:少了浪费了系统资源,多了造成系统拥挤效率不高.用线程池控制线程数量,其他线 ...

  8. 数组转换成json

    下面是详细的步骤,也可参考http://blog.csdn.net/wangliqiang1014/article/details/19924727 iOS数组可以转换车json对象,转换代码:NSS ...

  9. 类库探源——System.String

    一.MSDN描述 String 类: 表示文本,即一系列的 Unicode 字符 命名空间 : System 程序集 : mscorlib.dll 继承关系: 备注: 1. 字符串是 Unicode ...

  10. xmlns:tools="http://schemas.android.com/tools"以及tools:context=".ConfActivity"是什么意思

    xmlns:tools="http://schemas.android.com/tools"这个是xml的命名空间,有了他,你就可以alt+/作为提示,提示你输入什么,不该输入什么 ...