UVA-11107 Life Forms(后缀数组)
题目大意:给出n个字符串,找出所有最长的在超过一半的字符串中出现的子串。
题目分析:将所有的字符串连成一个,二分枚举长度,每次用O(n)的时间复杂度判断。连接字符串的时候中间添一个没有出现过的字符。
代码如下:
# include<iostream>
# include<cstdio>
# include<cstring>
# include<algorithm>
using namespace std;
# define mid (l+(r-l)/2)
# define LL long long const int N=100000; char s[N+105];
int SA[N+105],tSA[N+105];
int rk[N+105],cnt[N+105];
int height[N+105];
int flag[N+105];
bool vis[105]; int idx(char c)
{
return c-'a';
} bool same(int i,int j,int k,int n)
{
if(tSA[SA[i]]!=tSA[SA[j]]) return false;
if(SA[i]+k>=n&&SA[j]+k>=n) return true;
if(SA[i]+k<n&&SA[j]+k>=n) return false;
if(SA[i]+k>=n&&SA[j]+k<n) return false;
return tSA[SA[i]+k]==tSA[SA[j]+k];
} void buildSA()
{
int m=27;
int n=strlen(s);
for(int i=0;i<m;++i) cnt[i]=0;
for(int i=0;i<n;++i) ++cnt[rk[i]=idx(s[i])];
for(int i=1;i<m;++i) cnt[i]+=cnt[i-1];
for(int i=n-1;i>=0;--i) SA[--cnt[rk[i]]]=i; for(int k=1;k<=n;k<<=1){
int p=0;
for(int i=n-k;i<n;++i) tSA[p++]=i;
for(int i=0;i<n;++i) if(SA[i]>=k) tSA[p++]=SA[i]-k; for(int i=0;i<m;++i) cnt[i]=0;
for(int i=0;i<n;++i) ++cnt[rk[tSA[i]]];
for(int i=1;i<m;++i) cnt[i]+=cnt[i-1];
for(int i=n-1;i>=0;--i) SA[--cnt[rk[tSA[i]]]]=tSA[i]; swap(rk,tSA);
rk[SA[0]]=0;
p=1;
for(int i=1;i<n;++i){
if(same(i,i-1,k,n)) rk[SA[i]]=p-1;
else rk[SA[i]]=p++;
}
if(p>=n) break;
m=p;
}
} void getHeight()
{
int n=strlen(s);
for(int i=0;i<n;++i) rk[SA[i]]=i;
int k=0;
for(int i=0;i<n;++i){
if(rk[i]==0)
height[rk[i]]=k=0;
else{
if(k) --k;
int j=SA[rk[i]-1];
while(s[i+k]==s[j+k]) ++k;
height[rk[i]]=k;
}
}
} bool judge(int x,int n)
{
memset(vis,false,sizeof(vis));
vis[flag[SA[0]]]=true;
int k=1;
int len=strlen(s);
for(int i=1;i<len;++i){
if(k>n) return true;
if(flag[SA[i]]==-1)
break;
if(height[i]<x){
k=0;
memset(vis,false,sizeof(vis));
}
if(!vis[flag[SA[i]]]){
vis[flag[SA[i]]]=true;
++k;
}
}
return k>n;
} int f(int l,int r,int n)
{
++r;
while(l<r){
if(judge(mid,n)) l=mid+1;
else r=mid;
}
return r-1;
} bool ok(int i,int j)
{
return flag[i]==flag[j];
} void print(int p,int n)
{
int len=strlen(s);
memset(vis,false,sizeof(vis));
int k=1;
vis[flag[SA[0]]]=true;
for(int i=1;i<len;++i){
if(flag[SA[i]]==-1||height[i]<p){
if(k>n&&ok(SA[i-1],SA[i-1]+p-1)){
for(int j=SA[i-1];j<SA[i-1]+p;++j) printf("%c",s[j]);
puts("");
}
if(flag[SA[i]]==-1) break;
k=0;
memset(vis,false,sizeof(vis));
}
if(!vis[flag[SA[i]]]){
++k;
vis[flag[SA[i]]]=true;
}
}
} int main()
{
int n;
bool yy=false;
while(scanf("%d",&n)&&n)
{
if(yy) puts("");
yy=true;
if(n==1){
scanf("%s",s);
printf("%s\n",s);
}else{
memset(flag,-1,sizeof(flag));
s[0]=0;
int high=0;
for(int i=0;i<n;++i){
int m=strlen(s);
scanf("%s",s+m);
int nm=strlen(s);
for(int j=m;j<nm;++j) flag[j]=i;
s[nm]='z'+1;
s[nm+1]=0;
high=max(nm-m,high);
}
buildSA();
getHeight();
int len=f(0,high,n>>1);
if(len<=0) printf("?\n");
else print(len,n>>1);
}
}
return 0;
}
UVA-11107 Life Forms(后缀数组)的更多相关文章
- POJ 3294 UVA 11107 Life Forms 后缀数组
相同的题目,输出格式有区别. 给定n个字符串,求最长的子串,使得它同时出现在一半以上的串中. 不熟悉后缀数组的童鞋建议先去看一看如何用后缀数组计算两个字符串的最长公共子串 Ural1517 这道题的思 ...
- 后缀数组LCP + 二分 - UVa 11107 Life Forms
Life Forms Problem's Link Mean: 给你n个串,让你找出出现次数大于n/2的最长公共子串.如果有多个,按字典序排列输出. analyse: 经典题. 直接二分判断答案. 判 ...
- UVA - 11107 Life Forms (广义后缀自动机+后缀树/后缀数组+尺取)
题意:给你n个字符串,求出在超过一半的字符串中出现的所有子串中最长的子串,按字典序输出. 这道题算是我的一个黑历史了吧,以前我的做法是对这n个字符串建广义后缀自动机,然后在自动机上dfs,交上去AC了 ...
- UVA 11107 Life Forms——(多字符串的最长公共子序列,后缀数组+LCP)
题意: 输入n个序列,求出一个最大长度的字符串,使得它在超过一半的DNA序列中连续出现.如果有多解,按照字典序从小到大输出所有解. 分析:这道题的关键是将多个字符串连接成一个串,方法是用不同的分隔符把 ...
- UVA 12206 - Stammering Aliens(后缀数组)
UVA 12206 - Stammering Aliens 题目链接 题意:给定一个序列,求出出现次数大于m,长度最长的子串的最大下标 思路:后缀数组.搞出height数组后,利用二分去查找就可以 这 ...
- UVA11107 Life Forms --- 后缀数组
UVA11107 Life Forms 题目描述: 求出出现在一半以上的字符串内的最长字符串. 数据范围: \(\sum len(string) <= 10^{5}\) 非常坑的题目. 思路非常 ...
- UVA 11107(Life Forms-后缀数组+二分)
Problem C: Life Forms You may have wondered why most extraterrestrial life forms resemble humans, di ...
- POJ3294 Life Forms —— 后缀数组 最长公共子串
题目链接:https://vjudge.net/problem/POJ-3294 Life Forms Time Limit: 5000MS Memory Limit: 65536K Total ...
- UVA 10526 - Intellectual Property (后缀数组)
UVA 10526 - Intellectual Property 题目链接 题意:给定两个问题,要求找出第二个文本抄袭第一个文本的全部位置和长度,输出前k个,按长度从大到小先排.长度一样的按位置从小 ...
- Poj 3294 Life Forms (后缀数组 + 二分 + Hash)
题目链接: Poj 3294 Life Forms 题目描述: 有n个文本串,问在一半以上的文本串出现过的最长连续子串? 解题思路: 可以把文本串用没有出现过的不同字符连起来,然后求新文本串的heig ...
随机推荐
- Effective Objective-C 2.0 学习记录
由于最近入职,公司安排自由学习,于是有时间将Effective Objective-C 2.0一书学习了一遍.由于个人知识面较窄,对于书中有些内容无法理解透彻,现将所学所理解内容做一遍梳理,将个人认为 ...
- python pymongo-ensure_index
create_index 与 ensure_index 一.概述 ensure_index() 在mongoDB中创建索引 看了[1]感觉自己有些断章取义 ----------41316-- 参考链接 ...
- json 后台传前台
jsonObject需实例化new.jsonObject=new JSONObject();jsonObject.put("goodslist", list);jsonObject ...
- Software Engineering: 1. Introduction
Resource: Ian, Sommerville, Software Engineering 1. Professional software development 1.1 Software e ...
- 浅谈HTTP协议(下)
下面来讲响应消息.响应消息也分为响应起始行.响应头部.CRLF.响应主体. 响应起始行包括协议版本.响应状态码.原因短句.这里的重点就是响应状态码,它一共分为5类,状态码准确的说是一个三位数. 1xx ...
- informix dbaccess 常用执行方式及常见技巧
假设: A.数据库servername: testserver B.数据库名:testdb C.SQL脚本文件: sqlfile.sql create table test_table(c1 inte ...
- Eclipse新建web项目正常启动tomcat不报错,但不能访问项目的解决方法
原因: 虽然我手动添加了自己下载的tomcat,但是由于在Eclipse中创建Server时,"Server Locations"选项采用的时默认配置,即"Use wo ...
- Less基础知识~~~实现css
首先献上我学习网址 http://www.bootcss.com/lesscss.html 就是通过less.js的调用,更好的实现css样式布局,更简易化. 最近看前端的职位要求需简单理解less之 ...
- 使用Settings.settings存储用户的个性化配置
1.在vs中设计要存储的字段,如:zbl,注意范围选择用户 读取: var aa = Properties.Settings.Default.zbl; 写入: Properties.Settings. ...
- java web图片上传和文件上传
图片上传和文件上传本质上是一样的,图片本身也是文件.文件上传就是将图片上传到服务器,方式虽然有很多,但底层的实现都是文件的读写操作. 注意事项 1.form表单一定要写属性enctype=" ...