• UVAL 7902 2016ECfinal F


    题意:

    给出n个串,求一个最短的第一个串的子串使它不在其他的n-1个串中出现,若有多个求字典序最小的。

    Limits: • 1 ≤ T ≤ 42. • 2 ≤ N ≤ 50000. • N ≤ S1 + S2 + · · · + SN ≤ 250000. • the sum of Si in all test cases doesn’t exceed 3 × 106 .

    Sample Input

    3

    2

    aba

    bab

    3

    qnu

    cvbb

    bnu

    3

    a

    aa

    aaa

    Sample Output

    Case #1: aba

    Case #2: q

    Case #3: Impossible

    代码:

    //这么多串肯定要把他们连接起来(之间用没出现的字符隔开)。后缀数组求出heigh数组,答案要求字典序最小所以后缀数组从前向后找即可,每找到
    //一个在第一个串中的i位置时,在该位置向前和向后各找到第一个不在第一个串中的j那么lcp(i,j)一定是i位置和其他不在第一个串中后缀的
    //最长的lcp,那么这个lcp+1的长度就一定是在其他串中没有出现过,要求字典序最小所以要向后扩展一位,并且这个长度不能超出第一个串。
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int MAXN=300000;
    int t,n,sa[MAXN],he[MAXN],ra[MAXN],xx[MAXN],yy[MAXN],buc[MAXN];
    char s[MAXN],ch[MAXN];
    int len,len1,m;
    void get_suf()
    {
        int *x=xx,*y=yy;
        for(int i=0;i<m;i++) buc[i]=0;
        for(int i=0;i<len;i++) buc[x[i]=s[i]]++;
        for(int i=1;i<m;i++) buc[i]+=buc[i-1];
        for(int i=len-1;i>=0;i--) sa[--buc[x[i]]]=i;
        for(int k=1;k<=len;k<<=1){
            int p=0;
            for(int i=len-1;i>=len-k;i--) y[p++]=i;
            for(int i=0;i<len;i++) if(sa[i]>=k) y[p++]=sa[i]-k;
            for(int i=0;i<m;i++) buc[i]=0;
            for(int i=0;i<len;i++) buc[x[y[i]]]++;
            for(int i=1;i<m;i++) buc[i]+=buc[i-1];
            for(int i=len-1;i>=0;i--) sa[--buc[x[y[i]]]]=y[i];
            swap(x,y);
            p=1;x[sa[0]]=0;
            for(int i=1;i<len;i++){
                if(y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k])
                    x[sa[i]]=p-1;
                else x[sa[i]]=p++;
            }
            if(p>=len) break;
            m=p;
        }
        for(int i=0;i<len;i++) ra[sa[i]]=i;
        int k=0;
        for(int i=0;i<len;i++){
            if(ra[i]==0) { he[0]=0;continue; }
            if(k) k--;
            int j=sa[ra[i]-1];
            while(s[i+k]==s[j+k]&&i+k<len&&j+k<len) k++;
            he[ra[i]]=k;
        }
    }
    void solve()
    {
        int ans=len,pos=-1;
        for(int i=0;i<len;i++){
            while(i<len&&sa[i]>=len1) i++;
            if(i>=len) break;
            int plcp=he[i];
            for(int j=i-1;j>=0;j--){
                if(sa[j]>=len1) break;
                plcp=min(plcp,he[j]);
            }
            int slcp=he[i+1];
            for(int j=i+1;j<=len;j++){
                if(sa[j]>=len1) break;
                slcp=min(slcp,he[j]);
            }
            plcp=max(plcp,slcp);
            if(plcp<len1-sa[i]){
                if(plcp+1<ans){
                    ans=plcp+1;
                    pos=sa[i];
                }
            }
        }
    
        if(pos==-1) puts("Impossible");
        else{
            for(int i=0;i<ans;i++)
                printf("%c",s[i+pos]);
            puts("");
        }
    }
    int main()
    {
        scanf("%d",&t);
        for(int cas=1;cas<=t;cas++){
            scanf("%d",&n);
            scanf("%s",s);
            len=len1=strlen(s);
            for(int i=2;i<=n;i++){
                s[len++]='#';
                scanf("%s",s+len);
                len=strlen(s);
            }
            m=200;
            get_suf();
            printf("Case #%d: ",cas);
            solve();
        }
        return 0;
    }
  • 相关阅读:
    poj_1274The Perfect Stall
    USACO历年比赛的数据和解题报告
    最近公共祖先(least common ancestors algorithm)
    poj_1273Drainage Ditches
    oracle中type的使用
    乐观锁和悲观锁
    java 邮件服务器之james安装配置
    乐观锁和悲观锁
    oracle中type的使用
    java 邮件服务器之james安装配置
  • 原文地址:https://www.cnblogs.com/--ZHIYUAN/p/7976646.html
Copyright © 2020-2023  润新知