poj3294
来源:互联网 发布:蝙蝠风弄网络原版 编辑:程序博客网 时间:2024/06/08 05:11
【题意】
n个字符串,求最长的出现在多于一半字符串中的子串
【输入】
多组数据
每组第一行一个n表示n个字符串
接下来n行是n个字符串
【输出】
对于每组答案,输出最长的出现在多于一半字符串中的子串,如有多个,按字典序输出
若不存在,则输出'?'
两组数据答案之间用空行分隔
后缀数组经典运用之一
二分答案,然后按height分组,看每组来自多少个不同的字符串
注意n=1的情况program poj3294;var n,m,i,j,k,tot,ans,s,e,mid,limit,max:longint; ok:boolean; root,temp:ansistring; belong,change,total,dl,now,keep,rank,sa,height:array [-1..110001] of longint; yes:array [0..1001] of boolean; fin:array [0..1001] of longint;procedure swap (var a,b:longint);var i:longint;begin i:=a; a:=b; b:=i;end;procedure qsort (s,e:longint);var i,j,k:longint;begin if s>=e then exit; i:=s; j:=e; k:=dl[(s+e) div 2]; while i<=j do begin while root[dl[i]]<root[k] do inc(i); while root[dl[j]]>root[k] do dec(j); if i>j then break; swap(dl[i],dl[j]); inc(i); dec(j); end; qsort(s,j); qsort(i,e);end;function search (mid:longint):boolean;begin search:=false; tot:=0; fillchar(yes,sizeof(yes),false); k:=1; yes[belong[sa[m+1]]]:=true; for i:=m+2 to n do begin if (height[i]<mid)or(fin[belong[sa[i]]]-sa[i]<mid) then begin if k>=limit then begin search:=true; inc(tot); dl[tot]:=sa[i-1]; end; k:=1; fillchar(yes,sizeof(yes),false); yes[belong[sa[i]]]:=true; continue; end; if not yes[belong[sa[i]]] then begin yes[belong[sa[i]]]:=true; inc(k); end; end; if k>=limit then begin search:=true; inc(tot); dl[tot]:=sa[i-1]; end;end;begin repeat readln(m); if m=0 then break; if m and 1 = 1 then limit:=m-m div 2 else limit:=m div 2 + 1; root:=''; max:=maxlongint; for i:=1 to m do begin readln(temp); if length(temp)<max then max:=length(temp); root:=root+temp+' '; end; if m=1 then begin writeln(temp); writeln; continue; end; n:=length(root); for i:=1 to n do dl[i]:=i; qsort(1,n); k:=1; for i:=1 to n do begin if root[dl[i]]<>root[dl[k]] then k:=i; rank[dl[i]]:=k; end; k:=0; while 1 shl k<n do begin for i:=1 to n do if i+(1 shl k)>n then change[i]:=0 else change[i]:=rank[i+(1 shl k)]; fillchar(total,sizeof(total),0); for i:=1 to n do inc(total[change[i]]); for i:=1 to n do total[i]:=total[i]+total[i-1]; for i:=1 to n do begin dl[total[change[i]-1]+1]:=i; inc(total[change[i]-1]); end; fillchar(total,sizeof(total),0); for i:=1 to n do inc(total[rank[i]]); for i:=2 to n do total[i]:=total[i]+total[i-1]; fillchar(now,sizeof(now),0); fillchar(keep,sizeof(keep),0); for i:=1 to n do begin if now[rank[dl[i]]]<>change[dl[i]] then begin now[rank[dl[i]]]:=change[dl[i]]; total[rank[dl[i]]-1]:=total[rank[dl[i]]-1]+keep[rank[dl[i]]]; keep[rank[dl[i]]]:=0; end; inc(keep[rank[dl[i]]]); rank[dl[i]]:=total[rank[dl[i]]-1]+1; end; inc(k); end; for i:=1 to n do sa[rank[i]]:=i; fillchar(height,sizeof(height),0); for i:=1 to n do begin if rank[i]=1 then continue; k:=height[rank[i-1]]-1; if k<0 then k:=0; while (i+k<=n)and(sa[rank[i]-1]+k<=n) and(root[i+k]=root[sa[rank[i]-1]+k]) do inc(k); height[rank[i]]:=k; end; k:=1; for i:=1 to n do if root[i]=' ' then begin fin[k]:=i; inc(k); end else belong[i]:=k; s:=0; e:=max; while s<>e do begin mid:=s+e-(s+e) div 2; if search(mid) then s:=mid else e:=mid-1; end; if s=0 then begin writeln('?'); writeln; continue; end; ok:=search(s); for i:=1 to tot do writeln(copy(root,dl[i],s)); writeln; until false;end.
- poj3294
- poj3294
- poj3294 二分+后缀数组
- Life Forms poj3294
- POJ3294--Life Forms
- poj3294 Life Forms
- poj3294 Life Forms
- POJ3294-Life Forms
- Poj3294 Life Forms
- POJ3294:Life Forms(后缀数组)
- 后缀数组 - poj3294 Life Forms
- POJ3294 Life Form 题解&代码
- poj3294 Life Forms - 后缀数组
- POJ3294 Life Forms 【后缀数组】
- Current Contest(poj3294,后缀数组)
- 【POJ3294】Life Forms【后缀数组】【二分】
- poj3294 Life Forms(后缀数组)
- [POJ3294]Life Forms(后缀数组+二分)
- ACE学习之ACE_INET_Addr,ACE_SOCK_Acceptor 源代码
- 九度oj1151
- 辞职了,好迷茫。。。。
- VB工程---百例45--同心圆.
- 自己新添加的一些NSDate的分类方法
- poj3294
- 编程开始
- base-kernel-实现策略
- 修改MyEclipse8.5的启动画面
- 风姿花传歌词
- C++ 简单文件读写
- 火柴题解
- 动态代理
- 枚举并隐藏窗口函数[汇编语言]