• [BZOJ1195] 最短母串


    E. 最短母串

    题目描述

    原题来自:HNOI 2006

    给定 n 个字符串 S1,S2,⋯,Sn1​​,S2​​,,Sn​​,要求找到一个最短的字符串 TTT,使得这 nnn 个字符串都是 TTT 的子串。

    输入格式

    第一行是一个正整数 n,表示给定的字符串的个数;

    以下的 n 行,每行有一个全由大写字母组成的字符串。

    输出格式

    只有一行,为找到的最短的字符串 T

    在保证最短的前提下,如果有多个字符串都满足要求,那么必须输出按字典序排列的第一个。

    样例

    样例输入

    2 
    ABCD
    BCDABC

    样例输出

    ABCDABC

    数据范围与提示

    对于全部数据,1≤n≤12,1≤∣Si∣≤50i​​50。

    AC自动机+状压dp。其实也不算是dp,没有状态转移方程,就是用到了状压的思路。

    网上大部分题解用的数组版AC自动机,看的我好难受…

    设f[i][j]为在trie图上i节点状态为j时的最短长度,插入和求fail指针时顺便求出到某个点能覆盖的字符串,指针实现时trie图中要多维护一些东西:id=++cnt(f数组用),val(字符串),ooo(此节点表示的字符),然后bfs,定义两个队列分别存储节点和当前状态,不断扩展,由于是bfs,当状态为全部含有时即为最优解。关键在于字符串的输出,可以直接记录s[i][j]为在trie图上i节点状态为j时的字符串,但是比较占内存,是可以被卡掉的,所以可以记录trie *jl[10000][1<<13](i节点状态为j时的上一个节点),sta[10000][1<<13]i节点状态为j时的上一个状态),输出:

     1 if(state==maxn)
     2 {    
     3     head=0;
     4     while(p!=root)
     5     {
     6         q1[++head]=p;
     7     int temp=sta[p->id][state];
     8     p=jl[p->id][state];                
     9     state=temp;
    10     }
    11     while(head)putchar((char)q1[head--]->ooo+'A');
    12     return;
    13 }

    完整代码

    #include<iostream>
    #include<cstdio>
    #include<bitset>
    #include<cstring>
    using namespace std;
    int cnt;
    struct trie
    {
        int count,id,val,ooo;
        trie *fail,*next[26];
        trie()
        {
            id=++cnt;
            ooo=count=0;fail=NULL;
            for(int i=0;i<26;i++)
            next[i]=NULL;
        }
    }*q[10000000],*root=new trie();
    int head,tail;
    void insert(char s[],trie *root,int t)
    {
        trie *p=root;
        int i=0,index;
        while(s[i])
        {
            index=s[i]-'A';
            if(p->next[index]==NULL)p->next[index]=new trie();
            p->next[index]->ooo=index;
            p->next[index]->val|=p->val;
            p=p->next[index];
            i++;
        }
        p->count++;
        p->val|=1<<(t-1);
    }
    void build_ac(trie *root)
    {    
        head=tail=0;
        q[++tail]=root;
        while(head!=tail)
        {
            trie *p=q[++head];
            for(int i=0;i<26;i++)
            if(p->next[i])
            {
                if(p==root) p->next[i]->fail=p;
                else        p->next[i]->fail=p->fail->next[i];
                p->next[i]->val|=p->next[i]->fail->val;
                q[++tail]=p->next[i];
            }
            else
                if(p==root) p->next[i]=p;
                else        p->next[i]=p->fail->next[i];
        }
    }
    int n;
    char keyword[100];
    int f[10000][1<<13];
    trie *jl[10000][1<<13];
    int sta[10000][1<<13];
    trie *q1[10000000];
    int q2[10000000];
    int inf,maxn;
    
    void bfs()
    {
        head=tail=0;
        q1[++tail]=root;q2[tail]=0;
        f[1][0]=0;
        while(head!=tail)
        {
            trie *p=q1[++head];
            int state=q2[head];
            bitset<4> tt(state);
            if(state==maxn)
            {    
                head=0;
                while(p!=root)
                {
                    q1[++head]=p;
                    int temp=sta[p->id][state];
                    p=jl[p->id][state];                
                    state=temp;
                }
                while(head)putchar((char)q1[head--]->ooo+'A');
                return;
            }
            for(int i=0;i<26;i++)
            {
                int id=p->next[i]->id;
                if(f[id][state|p->next[i]->val]==inf)
                {
                    q1[++tail]=p->next[i];
                    q2[tail]=state|p->next[i]->val;
                    f[id][state|p->next[i]->val]=f[p->id][state]+1;
                    jl[id][state|p->next[i]->val]=p;
                    sta[id][state|p->next[i]->val]=state;
                }
                
            }
        }
    }
    signed main()
    {
        //freopen("in.txt","r",stdin);
    
        cin>>n;
        for(int i=1;i<=n;i++)
        {
            scanf("%s",keyword);
            insert(keyword,root,i);
        }
        build_ac(root);
        inf=f[0][0];
        maxn=(1<<(n))-1;
        bfs();
    }
    View Code
    波澜前,面不惊。
  • 相关阅读:
    洛谷—— P2234 [HNOI2002]营业额统计
    BZOJ——3555: [Ctsc2014]企鹅QQ
    CodeVs——T 4919 线段树练习4
    python(35)- 异常处理
    August 29th 2016 Week 36th Monday
    August 28th 2016 Week 36th Sunday
    August 27th 2016 Week 35th Saturday
    August 26th 2016 Week 35th Friday
    August 25th 2016 Week 35th Thursday
    August 24th 2016 Week 35th Wednesday
  • 原文地址:https://www.cnblogs.com/Al-Ca/p/11073425.html
Copyright © 2020-2023  润新知