poj 3294 Life Forms【SA+二分】
先加入未出现字符间隔把n个串连起来,注意如果串开的char这个间隔字符不能溢出,把这个接起来的串跑SA,二分答案k,判断的时候把连续一段he>=k的分成一组,然后看着一段是否包含了>n/2的串的后缀。
统计是否出现这里可以用时间戳优化visit数组,就不用每次memset了
输出答案的时候和二分判断一样,找到合法的子串就输出
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=200005;
int m,n,wa[N],wb[N],wv[N],wsu[N],sa[N],rk[N],he[N],v[N],ti,de,bl[N];
char s[N],t[N];
bool cmp(int r[],int a,int b,int l)
{
return r[a]==r[b]&&r[a+l]==r[b+l];
}
void saa(char r[],int n,int m)
{
int *x=wa,*y=wb;
for(int i=0;i<=m;i++)
wsu[i]=0;
for(int i=1;i<=n;i++)
wsu[x[i]=r[i]]++;
for(int i=1;i<=m;i++)
wsu[i]+=wsu[i-1];
for(int i=n;i>=1;i--)
sa[wsu[x[i]]--]=i;
for(int j=1,p=1;j<n&&p<n;j<<=1,m=p)
{
p=0;
for(int i=n-j+1;i<=n;i++)
y[++p]=i;
for(int i=1;i<=n;i++)
if(sa[i]>j)
y[++p]=sa[i]-j;
for(int i=1;i<=n;i++)
wv[i]=x[y[i]];
for(int i=0;i<=m;i++)
wsu[i]=0;
for(int i=1;i<=n;i++)
wsu[wv[i]]++;
for(int i=1;i<=m;i++)
wsu[i]+=wsu[i-1];
for(int i=n;i>=1;i--)
sa[wsu[wv[i]]--]=y[i];
swap(x,y);
p=1;
x[sa[1]]=1;
for(int i=2;i<=n;i++)
x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p:++p;
}
for(int i=1;i<=n;i++)
rk[sa[i]]=i;
for(int i=1,j,k=0;i<=n;he[rk[i++]]=k)
for(k?k--:0,j=sa[rk[i]-1];r[i+k]==r[j+k];k++);
}
bool ok(int w)
{
for(int i=2,la;i<=n;i=la+1)
{
la=i;
ti++;
int sm=0;
v[bl[sa[la-1]]]=ti,sm++;
while(he[la]>=w)
{
if(v[bl[sa[la]]]!=ti)
v[bl[sa[la]]]=ti,sm++;
la++;
}//cerr<<i<<" "<<la<<" "<<sm<<endl;
if(sm>m/2)
return 1;
}
return 0;
}
int main()
{
while(scanf("%d",&m)&&m)
{
n=0,de=26;
for(int j=1;j<=m;j++)
{
scanf("%s",t+1);
for(int i=1,len=strlen(t+1);i<=len;i++)
s[++n]=t[i]-'a',bl[n]=j;
s[++n]=++de,bl[n]=j;
}
saa(s,n,200);
int l=0,r=1000,ans=0;
while(l<=r)
{
int mid=(l+r)>>1;
if(ok(mid))
l=mid+1,ans=mid;
else
r=mid-1;
}//cerr<<ans<<endl;
if(ans==0)
{
puts("?\n");
continue;
}
for(int i=2,la;i<=n;i=la+1)
{
la=i;
ti++;
int sm=0;
v[bl[sa[la-1]]]=ti,sm++;
while(he[la]>=ans)
{
if(v[bl[sa[la]]]!=ti)
v[bl[sa[la]]]=ti,sm++;
la++;
}
if(sm>m/2)
{
for(int j=0;j<ans;j++)
if(s[sa[i]+j]<=26)
printf("%c",s[sa[i]+j]+'a');
puts("");
}
}
puts("");
}
return 0;
}
poj 3294 Life Forms【SA+二分】的更多相关文章
- Poj 3294 Life Forms (后缀数组 + 二分 + Hash)
题目链接: Poj 3294 Life Forms 题目描述: 有n个文本串,问在一半以上的文本串出现过的最长连续子串? 解题思路: 可以把文本串用没有出现过的不同字符连起来,然后求新文本串的heig ...
- POJ 3294 Life Forms [最长公共子串加强版 后缀数组 && 二分]
题目:http://poj.org/problem?id=3294 Life Forms Time Limit: 5000MS Memory Limit: 65536K Total Submiss ...
- POJ 3294 Life Forms(后缀数组+二分答案)
[题目链接] http://poj.org/problem?id=3294 [题目大意] 求出在至少在一半字符串中出现的最长子串. 如果有多个符合的答案,请按照字典序输出. [题解] 将所有的字符串通 ...
- poj 3294 Life Forms - 后缀数组 - 二分答案
题目传送门 传送门I 传送门II 题目大意 给定$n$个串,询问所有出现在严格大于$\frac{n}{2}$个串的最长串.不存在输出'?' 用奇怪的字符把它们连接起来.然后求sa,hei,二分答案,按 ...
- POJ 3294 Life Forms 后缀数组+二分 求至少k个字符串中包含的最长子串
Life Forms Description You may have wondered why most extraterrestrial life forms resemble humans, ...
- 字符串(后缀数组):POJ 3294 Life Forms
Life Forms Description You may have wondered why most extraterrestrial life forms resemble humans, d ...
- poj 3294 Life Forms
后缀数组的题目,把后缀连接起来,这个还是先二分答案,然后选取一段连续的height值,判断这些height代表的后缀有没有覆盖一半以上的字符串. 得出答案的长度之后还要在枚举连续的heigh,判断有没 ...
- poj 3294 Life Forms(后缀数组)
题意:给你最多100个字符串,求最长的且是一半以上的字符串的公共子串,如果有多个,按字典序输出. 思路:先把各个串拼起来,中间加上一个之前未出现过的字符,然后求后缀.然后根据h数组和sa数组,求出最长 ...
- POJ 3294 n个串中至少一半的串共享的最长公共子串
Life Forms Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 12484 Accepted: 3502 Descr ...
随机推荐
- Effective C++ 条款13/14 以对象管理资源 || 在资源管理类中小心拷贝行为
三.资源管理 资源就是一旦你使用了它,将来不用的时候必须归还系统.C++中最常用的资源就是动态内存分配.其实,资源还有 文件描述符.互斥器.图形界面中的字形.画刷.数据库连接.socket ...
- PJzhang:python基础入门的7个疗程-two
猫宁!!! 参考链接:易灵微课-21天轻松掌握零基础python入门必修课-售价29元人民币 https://www.liaoxuefeng.com/wiki/1016959663602400 htt ...
- 网页JS简繁体字转换
用法:非得加上html头 utf-8编码 其它编码无测试 head 中引用 <script language='javascript' src='zh.js'></script> ...
- poj 3105 Expectation 按位统计
题意: 给n,求sum(i^j)/(n^2),0<=i,j<n.n<10^9 分析: 暴力n^2算法肯定超时.这是logn按位统计算法:按位先算出0出现的个数x,则1出现的个数为n- ...
- for in 与for of
最近在项目中需要用到遍历对象,用ES6 for of对象后报如下错误 TypeError: [object Object] is not iterable!,网上查询阮大神的教程发现“ES6 的有些 ...
- iOS 各种编译错误汇总
1.error: macro names must be identifiers YourProject_prefix.pch 原因: 因为你弄脏了预处理器宏,在它处于<Multiple Val ...
- ORACLE数据库忘记SYS和SYSTEM密码,SYSTEM被锁定怎么办?
本人忘性太大,竟然将ORACLE的Sys用户和system用户密码搞忘,而且多次尝试登录system后,造成system被锁定. 经过一番尝试,终于解决.过程如下: 首先,重建sys密码文件.重建方式 ...
- 安装sbt
http://www.scala-sbt.org/0.13/docs/zh-cn/Installing-sbt-on-Linux.html [root@hadoop1 target]# curl ht ...
- 通过命令打包apk
平时使用android studio打包,方便快捷,对命令不太熟悉,但在上传apk包到应用市场时,需要认领apk,“认领页的[选择APK]”不是上传您要更新的APK应用文件,而是下载我们提供的空包文件 ...
- CSS3 (一)
属性选择器 1. E[attr^="value"]:指定了属性名,并且有属性值,属性值是以value开头的: .wrap a[href^="http://"]{ ...