poj 3294 Life Forms(后缀数组)
题意:给你最多100个字符串,求最长的且是一半以上的字符串的公共子串,如果有多个,按字典序输出。
思路:先把各个串拼起来,中间加上一个之前未出现过的字符,然后求后缀。然后根据h数组和sa数组,求出最长的公共串。
#include<stdio.h>
#include<string.h>
#include<algorithm>
using std::sort;
#define V 220000
int r[V],sa[V],h[V],a[V],b[V],X[V],Y[V];
int acl[120],len[110],tot,mark[V],mark_len,be[V],m[110],max_len;
char s[V],out1[V],out2[V];
void calh(int n)
{
int i,j,k=0;
for(i=1; i<=n; i++)r[sa[i]]=i;
for(i=0; i<n; h[r[i++]]=k)
for(k? k-- :0,j=sa[r[i]-1];a[i+k]==a[j+k];k++);
}
bool cmp(int *r,int a,int b,int le)
{
return (r[a]==r[b]&&r[a+le]==r[b+le]);
}
void suffix(int n,int m=128)
{
int i,j,*x=X,*y=Y,*t,p;
for(i=0;i<m;i++)b[i]=0;
for(i=0;i<n;i++)b[x[i]=a[i]]++;
for(i=1;i<m;i++)b[i]+=b[i-1];
for(i=n-1;i>=0;i--)sa[--b[x[i]]]=i;
for(j=1,p=1;p<n;m=p,j<<=1)
{
p=0;
for(i=n-j;i<n;i++)y[p++]=i;
for(i=0; i<n;i++)if(sa[i]>=j)y[p++]=sa[i]-j;
for(i=0; i<m;i++)b[i]=0;
for(i=0; i<n;i++)b[x[y[i]]]++;
for(i=1; i<m;i++)b[i]+=b[i-1];
for(i=n-1;i>=0;i--)sa[--b[x[y[i]]]]=y[i];
for(t=x,x=y,y=t,x[sa[0]]=0,i=1,p=1;i<n;i++)
x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
}
calh(n-1);
}
void judge(int n)//先预处理每个sa属于哪个串
{
int i,j,k;
for(i=1;i<=n;i++)
{
for(j=1;j<=tot;j++)
{
if(sa[i]==len[j]){
be[i]=0;
break;
}
if(sa[i]<len[j]){
be[i]=j;
break;
}
}
}
}
int mm[110];
int getmin(int s)//排序得到当前最长的公共串长度
{
for(int i=1;i<=tot;i++)mm[i]=m[i];
sort(mm+1,mm+1+tot);
return mm[tot+1-s];
}
void solve(int n)
{
int cou=tot/2+1,cur=0,cur_len=0,i,j;//cou表示至少需要的串的数量,cur表示目前的子串所在的串的数量,cur_len表示目前子串的长度
judge(n);
memset(m,0,sizeof(m));//m表示各个串包含的子串的长度
for(i=1;i<=n;i++)
{
for(j=1;j<=tot;j++)if(m[j]>h[i])//更新mi
m[j]=h[i];
if(h[i]<max_len){
cur=0;continue;
}
if(h[i]>m[be[i]]){
if(m[be[i]]==0||m[be[i]]<max_len)cur++;
m[be[i]]=h[i];
}
if(h[i]>m[be[i-1]]){
if(m[be[i-1]]==0||m[be[i-1]]<max_len)cur++;
m[be[i-1]]=h[i];
}
if(cur>=cou){
cur_len=getmin(cou);
if(cur_len>max_len)
{
mark_len=1;
mark[0]=sa[i];
max_len=cur_len;
}
else if(cur_len==max_len)
mark[mark_len++]=sa[i];
}
}
}
int main()
{
int i,j,k,t,n;
for(i=1;i<=96;i++)acl[i]=i;
for(i=97;i<=110;i++)acl[i]=i+26;
while(scanf("%d",&t)!=-1&&t)
{
len[0]=-1;
for(i=1;i<=t;i++)
{
scanf("%s",s+len[i-1]+1);
len[i]=strlen(s);
s[len[i]]=acl[i];
}
s[len[t]]=0;
n=strlen(s);
for(i=0;i<n;i++)a[i]=s[i];
a[n]=0;
suffix(n+1);
mark_len=0;max_len=0;tot=t;
solve(n);
if(max_len==0)
printf("?\n\n");
else{
strcpy(out1,s+mark[0]);
out1[max_len]=0;
puts(out1);
for(i=1;i<mark_len;i++){
strcpy(out2,s+mark[i]);
out2[max_len]=0;
if(strcmp(out1,out2)==0)continue;
strcpy(out1,out2);
puts(out1);
}
puts("");
}
}
return 0;
}
poj 3294 Life Forms(后缀数组)的更多相关文章
- Poj 3294 Life Forms (后缀数组 + 二分 + Hash)
题目链接: Poj 3294 Life Forms 题目描述: 有n个文本串,问在一半以上的文本串出现过的最长连续子串? 解题思路: 可以把文本串用没有出现过的不同字符连起来,然后求新文本串的heig ...
- 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(后缀数组+二分答案)
[题目链接] http://poj.org/problem?id=3294 [题目大意] 求出在至少在一半字符串中出现的最长子串. 如果有多个符合的答案,请按照字典序输出. [题解] 将所有的字符串通 ...
- POJ 3294 Life Forms [最长公共子串加强版 后缀数组 && 二分]
题目:http://poj.org/problem?id=3294 Life Forms Time Limit: 5000MS Memory Limit: 65536K Total Submiss ...
- POJ 3294 UVA 11107 Life Forms 后缀数组
相同的题目,输出格式有区别. 给定n个字符串,求最长的子串,使得它同时出现在一半以上的串中. 不熟悉后缀数组的童鞋建议先去看一看如何用后缀数组计算两个字符串的最长公共子串 Ural1517 这道题的思 ...
- POJ 1743 Musical Theme 后缀数组 最长重复不相交子串
Musical ThemeTime Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://poj.org/problem?id=1743 Description ...
- POJ 1226 Substrings(后缀数组+二分答案)
[题目链接] http://poj.org/problem?id=1226 [题目大意] 求在每个给出字符串中出现的最长子串的长度,字符串在出现的时候可以是倒置的. [题解] 我们将每个字符串倒置,用 ...
- POJ 3080 Blue Jeans 后缀数组, 高度数组 难度:1
题目 http://poj.org/problem?id=3080 题意 有m个(2<=m<=10)不包含空格的字符串,长度为60个字符,求所有字符串中都出现过的最长公共子序列,若该子序列 ...
- UVA11107 Life Forms --- 后缀数组
UVA11107 Life Forms 题目描述: 求出出现在一半以上的字符串内的最长字符串. 数据范围: \(\sum len(string) <= 10^{5}\) 非常坑的题目. 思路非常 ...
随机推荐
- 配置nginx支持thinkphp框架
因为nginx本身没有支持pathinfo,所以无法使用thinkphp框架,不过我们可以在配置里进行修改使其能够正常使用thinkphp. 1.修改配置支持pathinfo vi /etc/ngin ...
- odoo 错误 Resource interpreted as Stylesheet but transferred with MIME type application/x-css:
odoo8 页面内容显示一半, web 控制台显示错误 Resource interpreted as Stylesheet but transferred with MIME type ap ...
- dispatch队列
GCD编程的核心就是dispatch队列,dispatch block的执行最终都会放进某个队列中去进行,它类似NSOperationQueue但更复杂也更强大,并且可以嵌套使用.所以说,结合bloc ...
- Android开源项目发现---Spinner选择器与日历选择器篇(持续更新)
1. android-times-square Android日历部件 支持选取单个日期,多个日期,及日期区间段和对话框形式显示 项目地址:https://github.com/square/andr ...
- android--使用Struts2服务端与android交互
一,服务器端: web.xml文件: <?xml version="1.0" encoding="UTF-8"?> <web-app vers ...
- 查看linux内存、cpu
1.查看cpu数 多核cpu,包括物理多核和逻辑多核,一台机器可能有多个cpu,每个cpu可能有多核的,多个可能包括物理多核和逻辑多核. /proc/cpuinfo 文件里记录了这些信息,以下是一个核 ...
- 执行计划之CONCATENATION
CREATE TABLE T_CONCAT (ID NUMBER, NAME VARCHAR2(30), TYPE VARCHAR2(30)); INSERT INTO T_CONCAT SELECT ...
- Volley框架支持HTTPS请求。
第一次写帖子,嘿嘿. 最近了解到google2013IO大会出了个网络框架,正好项目也需要用到,就看了下. 最后发现接口都是HTTPS的,但是Volley默认是不支持HTTPS,网上找了好久,都没有对 ...
- Node.js权威指南 (6) - 在Node.js中操作文件系统
6.1 同步方法与异步方法 / 856.2 对文件执行读写操作 / 86 6.2.1 文件的完整读写 / 86 6.2.2 从指定位置处开始读写文件 / 916.3 创建与读取目录 / 97 6.3. ...
- 许令波老师的java的IO机制分析文章
深入分析 Java I/O 的工作机制 I/O 问题可以说是当今互联网 Web 应用中所面临的主要问题之一,因为当前在这个海量数据时代,数据在网络中随处流动.这个流动的过程中都涉及到 I/O 问题,可 ...