题意:给你最多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(后缀数组)的更多相关文章

  1. Poj 3294 Life Forms (后缀数组 + 二分 + Hash)

    题目链接: Poj 3294 Life Forms 题目描述: 有n个文本串,问在一半以上的文本串出现过的最长连续子串? 解题思路: 可以把文本串用没有出现过的不同字符连起来,然后求新文本串的heig ...

  2. poj 3294 Life Forms - 后缀数组 - 二分答案

    题目传送门 传送门I 传送门II 题目大意 给定$n$个串,询问所有出现在严格大于$\frac{n}{2}$个串的最长串.不存在输出'?' 用奇怪的字符把它们连接起来.然后求sa,hei,二分答案,按 ...

  3. POJ 3294 Life Forms 后缀数组+二分 求至少k个字符串中包含的最长子串

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

  4. POJ 3294 Life Forms(后缀数组+二分答案)

    [题目链接] http://poj.org/problem?id=3294 [题目大意] 求出在至少在一半字符串中出现的最长子串. 如果有多个符合的答案,请按照字典序输出. [题解] 将所有的字符串通 ...

  5. POJ 3294 Life Forms [最长公共子串加强版 后缀数组 && 二分]

    题目:http://poj.org/problem?id=3294 Life Forms Time Limit: 5000MS   Memory Limit: 65536K Total Submiss ...

  6. POJ 3294 UVA 11107 Life Forms 后缀数组

    相同的题目,输出格式有区别. 给定n个字符串,求最长的子串,使得它同时出现在一半以上的串中. 不熟悉后缀数组的童鞋建议先去看一看如何用后缀数组计算两个字符串的最长公共子串 Ural1517 这道题的思 ...

  7. POJ 1743 Musical Theme 后缀数组 最长重复不相交子串

    Musical ThemeTime Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://poj.org/problem?id=1743 Description ...

  8. POJ 1226 Substrings(后缀数组+二分答案)

    [题目链接] http://poj.org/problem?id=1226 [题目大意] 求在每个给出字符串中出现的最长子串的长度,字符串在出现的时候可以是倒置的. [题解] 我们将每个字符串倒置,用 ...

  9. POJ 3080 Blue Jeans 后缀数组, 高度数组 难度:1

    题目 http://poj.org/problem?id=3080 题意 有m个(2<=m<=10)不包含空格的字符串,长度为60个字符,求所有字符串中都出现过的最长公共子序列,若该子序列 ...

  10. UVA11107 Life Forms --- 后缀数组

    UVA11107 Life Forms 题目描述: 求出出现在一半以上的字符串内的最长字符串. 数据范围: \(\sum len(string) <= 10^{5}\) 非常坑的题目. 思路非常 ...

随机推荐

  1. requirejs 笔记

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http ...

  2. 疯狂的表单-html5新增表单元素和属性

    疯狂的表单 2015/11/27 16:44:07 从三方面来介绍html5表单的新特性 表单结构更灵活 要提交数据的控件可以布局在form标签之外,看下面的代码,表单元素可以写到form元素之外,只 ...

  3. 转:Ext GridPanel根据条件显示复选框

    Ext GridPanel实现复选框选择框: var selectModel = new Ext.grid.CheckboxSelectionModel({ singleSelect : false ...

  4. linux之GDB常用命令汇总

    查看gdb的版本号 (1)rpm -q gdb 会显示是否安装gdb及版本号 (2)gdb --version也可以 breakpoint b main; b 20; 设置断点 breakpoint ...

  5. 大数据计算新贵Spark在腾讯雅虎优酷成功应用解析

    http://www.csdn.net/article/2014-06-05/2820089 摘要:MapReduce在实时查询和迭代计算上仍有较大的不足,目前,Spark由于其可伸缩.基于内存计算等 ...

  6. 在线浏览pdf文件,pdfobject的简单使用

    该js插件,官网有详细的使用教程(网址:http://www.pdfobject.com/examples/).打开里面的例子后,查看新打开页面,打开并查看该页面的源代码. 需要的材料: 1.PDFo ...

  7. astyle基本功能介绍

    astyle是一个命令行工具,语法格式如下 astyle [options] < original > 例如: astyle --style=ansi foo.cpp 上面的命令将美化fo ...

  8. 关于IOS开发者账号一点总结

    经过查阅相关资料,我扼要总结了以下几点内容. 一.开发者账号类型 个人账号 99美金/年 公司账号 99 企业账号 299 教育账号 0 二.开发者账号有无比较 如果有: 可以真机测试 发布的应用可以 ...

  9. 了解 Windows Azure 存储计费 – 带宽、事务和容量

     我们收到关于如何估算 Windows Azure存储成本,以便了解如何更好地构建一个经济有效的应用程序的问题.在本文中,我们将从带宽.事务和容量这三种存储成本的角度探讨这一问题. 使用 Wind ...

  10. 使用VisualStudio进行单元测试之三

    私有方法需不需要测试,本文不做讨论.假设您也认为有时候,私有方法也需要进行测试,那就一起来看看如何进行私有方法的测试. 准备测试代码 测试用的代码还是前面测试时使用过的代码,不同之处就是在类中增加了一 ...