POJ3294--Life Forms 后缀数组+二分答案 大于k个字符串的最长公共子串
2015-04-22 21:38
399 查看
LifeForms
Description
Youmayhavewonderedwhymostextraterrestriallifeformsresemblehumans,differingbysuperficialtraitssuchasheight,colour,wrinkles,ears,eyebrowsandthelike.Afewbearnohumanresemblance;thesetypicallyhavegeometricoramorphousshapeslikecubes,oilslicksorcloudsofdust.
Theanswerisgiveninthe146thepisodeofStarTrek-TheNextGeneration,titledTheChase.Itturnsoutthatinthevastmajorityofthequadrant'slifeformsendedupwithalargefragmentofcommonDNA.
GiventheDNAsequencesofseverallifeformsrepresentedasstringsofletters,youaretofindthelongestsubstringthatissharedbymorethanhalfofthem.
Input
Standardinputcontainsseveraltestcases.Eachtestcasebeginswith1≤n≤100,thenumberoflifeforms.nlinesfollow;eachcontainsastringoflowercaselettersrepresentingtheDNAsequenceofalifeform.EachDNAsequencecontainsatleastoneandnotmorethan1000letters.Alinecontaining0followsthelasttestcase.
Output
Foreachtestcase,outputthelongeststringorstringssharedbymorethanhalfofthelifeforms.Iftherearemany,outputalloftheminalphabeticalorder.Ifthereisnosolutionwithatleastoneletter,output"?".Leaveanemptylinebetweentestcases.
SampleInput
SampleOutput
TimeLimit:5000MS | MemoryLimit:65536K | |
TotalSubmissions:10800 | Accepted:2967 |
Youmayhavewonderedwhymostextraterrestriallifeformsresemblehumans,differingbysuperficialtraitssuchasheight,colour,wrinkles,ears,eyebrowsandthelike.Afewbearnohumanresemblance;thesetypicallyhavegeometricoramorphousshapeslikecubes,oilslicksorcloudsofdust.
Theanswerisgiveninthe146thepisodeofStarTrek-TheNextGeneration,titledTheChase.Itturnsoutthatinthevastmajorityofthequadrant'slifeformsendedupwithalargefragmentofcommonDNA.
GiventheDNAsequencesofseverallifeformsrepresentedasstringsofletters,youaretofindthelongestsubstringthatissharedbymorethanhalfofthem.
Input
Standardinputcontainsseveraltestcases.Eachtestcasebeginswith1≤n≤100,thenumberoflifeforms.nlinesfollow;eachcontainsastringoflowercaselettersrepresentingtheDNAsequenceofalifeform.EachDNAsequencecontainsatleastoneandnotmorethan1000letters.Alinecontaining0followsthelasttestcase.
Output
Foreachtestcase,outputthelongeststringorstringssharedbymorethanhalfofthelifeforms.Iftherearemany,outputalloftheminalphabeticalorder.Ifthereisnosolutionwithatleastoneletter,output"?".Leaveanemptylinebetweentestcases.
SampleInput
3 abcdefg bcdefgh cdefghi 3 xxx yyy zzz 0
SampleOutput
bcdefg cdefgh ? 题意:n个字符串,求大于n/2个字符串的最长子串。如果有多个按字典序输出。 大致思路:首先把所有字符串用不相同的一个字符隔开(用同一个字符隔开wa了好久),这里我是用数字来隔开的。 然后依次求sa,lcp。我们可以二分答案的长度,对于长度x,我们可以把后缀进行分组(lcp[i]<x时隔开),然后对于每一组判断有多少个字符串出现,如果大于n/2说明符合。。对于字典序就不用排序了,,因为我们就是按照sa数组来遍历lcp的。。所以直接得到的答案就是字典序从小到大。
#include<set> #include<map> #include<cmath> #include<ctime> #include<queue> #include<stack> #include<cstdio> #include<string> #include<vector> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> usingnamespacestd; typedefunsignedlonglongull; typedeflonglongll; constintinf=0x3f3f3f3f; constdoubleeps=1e-8; constintM=2e6+10; ints[M]; intsa[M],tmp[M],rank[M],lcp[M],k,len; boolcmp(inti,intj) { if(rank[i]!=rank[j]) returnrank[i]<rank[j]; else { intx=i+k<=len?rank[i+k]:-1; inty=j+k<=len?rank[j+k]:-1; returnx<y; } } voidbuild_sa() { for(inti=0;i<=len;i++) { sa[i]=i; rank[i]=i<len?s[i]:-1; } for(k=1;k<=len;k*=2) { sort(sa,sa+len+1,cmp); tmp[sa[0]]=0; for(inti=1;i<=len;i++) { tmp[sa[i]]=tmp[sa[i-1]]+(cmp(sa[i-1],sa[i])?1:0); } for(inti=0;i<=len;i++) { rank[i]=tmp[i]; } } } voidGet_Lcp() { for(inti=0;i<len;i++) { rank[sa[i]]=i; } inth=0; lcp[0]=0; for(inti=0;i<len;i++) { intj=sa[rank[i]-1]; if(h>0) h--; for(;i+h<len&&j+h<len;h++) if(s[i+h]!=s[j+h]) break; lcp[rank[i]]=h; } } intvis[110],pos[M]; intans[M],tot; intStack[M],top; boolsolve(intx,intn) { intminv=inf; intcnt=0; boolflag=false; for(inti=0;i<=len+1;i++) { if(lcp[i]<x) { if(cnt+(!vis[pos[sa[i-1]]])>n/2&&(minv!=inf&&minv>=x)) { if(!flag) tot=0; flag=true; ans[tot++]=sa[i-1]; } minv=inf; cnt=0; memset(vis,0,sizeof(vis)); continue; } if(vis[pos[sa[i-1]]]==0) { cnt++; } vis[pos[sa[i-1]]]=1; minv=min(minv,lcp[i]); } returntot>0&&flag; } intstring_len[110],c1; voidinit() { c1=tot=0; memset(vis,0,sizeof(vis)); memset(string_len,0,sizeof(string_len)); } charcacaca[1100]; intmain() { #ifndefONLINE_JUDGE freopen("in.txt","r",stdin); //freopen("wa.txt","w",stdout); #endif intn,cas=1; while(scanf("%d",&n),n) { if(cas!=1) printf("\n"); cas++; init(); len=0; intdel=1; for(inti=0;i<n;i++) { scanf("%s",cacaca); intsub_len=strlen(cacaca); for(intj=0;j<sub_len;j++) { s[len++]=cacaca[j]; } s[len++]=M+del; del++; string_len[c1]=sub_len+string_len[c1-1]; if(c1) string_len[c1]++; c1++; } if(n==1) { for(inti=0;i<len-1;i++) { printf("%c",s[i]); } continue; } for(inti=0,j=0;i<len;i++) { if(i>=string_len[j]) { pos[i]=-1; j++; continue; } pos[i]=j+1; } build_sa(); Get_Lcp(); intua=0,ub=M; while(ua+1<ub) { intmid=(ua+ub)>>1; if(mid&&solve(mid,n)==true) { ua=mid; } else ub=mid; } if(tot==0) printf("?\n"); else { if(ua==0) { printf("?\n"); continue; } for(inti=0;i<tot;i++) { for(intj=ans[i];j<ans[i]+ua;j++) { printf("%c",s[j]); } printf("\n"); } } } return0; }
相关文章推荐
- 【poj3294-不小于k个字符串中最长公共子串】后缀数组
- poj 3294 求多于k个字符串的最长公共子串的个数-------后缀数组+二分答案
- poj3294(不小于k个字符串中的最长子串---后缀数组)
- poj3294 Life Forms(后缀数组+大于k/2个字符串中含有的最长公共子串)
- POJ3294 出现在至少k个字符串中的最长子串
- POJ 题目3294Life Forms(后缀数组求超过k个的串的最长公共子串)
- 字符串hash + 二分答案 - 求最长公共子串 --- poj 2774
- poj 2774 最长公共子串--字符串hash或者后缀数组或者后缀自动机
- 后缀数组(多个字符串的最长公共子串)—— POJ 3294
- 【POJ 3294】Life Forms 不小于k个字符串中的最长子串
- POJ 3415 Life Forms 给定n个字符串,求出现在不小于k个字符串中的最长子串。
- 字符串hash + 二分答案 - 求最长公共子串 --- poj 2774
- bupt 204 Palindrome 求字符串任意区间的最长回文子串 二分答案+后缀数组
- POJ 3294 Life Forms(不小于k个字符串中的最长子串 后缀数组)
- Life Forms 后缀数组 不小于k个字符串中的最长子串
- POJ 3294 Life Forms (后缀数组,求出现在不少于k个字符串的最长子串)
- poj 2774 求两字符串的最长公共子串 后缀数组
- poj 3294 Life Forms 求n(n>1)个字符串的最长的一个子串 后缀数组
- POJ 3294 Life Forms (后缀数组,求出现在不少于k个字符串的最长子串)
- poj 2774 Long Long Message 求两个字符串的最长公共子串 后缀数组