Live2d Test Env

POJ3294Life Forms(广义后缀自动机)(后缀数组+二分+数状数组)

You may have wondered why most extraterrestrial life forms resemble humans, differing by superficial traits such as height, colour, wrinkles, ears, eyebrows and the like. A few bear no human resemblance; these typically have geometric or amorphous shapes like cubes, oil slicks or clouds of dust.

The answer is given in the 146th episode of Star Trek - The Next Generation, titled The Chase. It turns out that in the vast majority of the quadrant's life forms ended up with a large fragment of common DNA.

Given the DNA sequences of several life forms represented as strings of letters, you are to find the longest substring that is shared by more than half of them.

Input

Standard input contains several test cases. Each test case begins with 1 ≤ n ≤ 100, the number of life forms. n lines follow; each contains a string of lower case letters representing the DNA sequence of a life form. Each DNA sequence contains at least one and not more than 1000 letters. A line containing 0 follows the last test case.

Output

For each test case, output the longest string or strings shared by more than half of the life forms. If there are many, output all of them in alphabetical order. If there is no solution with at least one letter, output "?". Leave an empty line between test cases.

Sample Input

3
abcdefg
bcdefgh
cdefghi
3
xxx
yyy
zzz
0

Sample Output

bcdefg
cdefgh

?

题意:

给定一些模板字符串,求一个最长公共字串,这个最长公共字串至少在一半以上的字符串里出现过。

思路:

把模板字符串都连接起来。二分长度,RMQ去验证。

 

 (服了,网上找不到广义后缀自动机的资料。。。)

 

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<memory>
#include<cmath>
#define maxn 350003
using namespace std;
int n,len,ans,Max,now;
char s[1010],cap[1010];
struct SAM
{
    int ch[maxn][26],fa[maxn],maxlen[maxn],Last,sz;
    int root,nxt[maxn],size[maxn];
    void init()
    {
        sz=0;
        root=++sz;
        memset(size,0,sizeof(size));
        memset(ch[1],0,sizeof(ch[1]));
        memset(nxt,0,sizeof(nxt));
    }
    void add(int x)
    {
        int np=++sz,p=Last;Last=np;
        memset(ch[np],0,sizeof(ch[np]));
        maxlen[np]=maxlen[p]+1;
        while(p&&!ch[p][x]) ch[p][x]=np,p=fa[p];
        if(!p) fa[np]=1;
        else {
            int q=ch[p][x];
            if(maxlen[p]+1==maxlen[q]) fa[np]=q;
            else {
                int nq=++sz;
                memcpy(ch[nq],ch[q],sizeof(ch[q]));size[nq]=size[q]; nxt[nq]=nxt[q];
                maxlen[nq]=maxlen[p]+1;
                fa[nq]=fa[q];
                fa[q]=fa[np]=nq;
                while(p&&ch[p][x]==q) ch[p][x]=nq,p=fa[p];
            }
        }
        for(;np;np=fa[np]) 
          if(nxt[np]!=now) {
              size[np]++;
              nxt[np]=now;
          }else break;
    }
    void dfs(int x,int d){//输出    
       if(d!=maxlen[x] || d>ans) return;
       if(maxlen[x]==ans && size[x]>n){ puts(cap); return; }
          for(int i=0;i<26;++i)
          if(ch[x][i]){ cap[d]=i+'a'; dfs(ch[x][i],d+1); cap[d]=0; }
    }
};
SAM Sam;
int main()
{
    while(~scanf("%d",&n)&&n){     
        Sam.init();
        for(int i=1;i<=n;i++) {
            scanf("%s",s+1);
            Sam.Last=Sam.root;
            len=strlen(s+1);
            now=i;
            for(int j=1;j<=len;j++) Sam.add(s[j]-'a');
        }
        Max=0;ans=0;n>>=1;
        for(int i=1;i<=Sam.sz;i++) 
            if(Sam.size[i]>n&&Sam.maxlen[i]>ans) { Max=i;ans=Sam.maxlen[i];}
        if(ans) Sam.dfs(1,0);
        else puts("?");
        puts("");
    }
    return 0;
}

 

 

 

参考:http://blog.csdn.net/JacaJava/article/details/78678612?locationNum=6&fps=1

 

posted @ 2017-12-11 17:42  nimphy  阅读(577)  评论(0编辑  收藏  举报