[HNOI2006]最短母串问题(AC自动机)

[HNOI2006]最短母串问题(luogu)

Solution

将所有串放到trie树上,每个点记录一个状态表示它可以作为哪些串的结尾

bfs搜索字典序最小的包含所有串结尾的母串

Code

 

#include <cstdio>
#include <cstdlib>
#include <queue>
using namespace std;
const int N=610,M=1<<12;
int L1[N*M],L2[N*M],head,tail,ans[N],S=1,fa[N],n,tot=1,trie[N][26],fail[N],state[N],id[N];
bool flag[N][M];
char s[51];
queue <int> q;
struct node
{
    int u,f;
};
queue <node> Q;
void add(int pos)
{
    int now=S;
    for(int i=0;s[i];i++)
    {
        int wh=s[i]-'A';
        if(!trie[now][wh]) trie[now][wh]=++tot;
        now=trie[now][wh];
    }
    state[now]|=(1<<pos);
}
void get_fail()
{
    for(int i=0;i<26;i++)
        if(trie[S][i]) q.push(trie[S][i]),fail[trie[S][i]]=S;
        else trie[S][i]=S;
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        state[u]|=state[fail[u]];
        for(int i=0;i<26;i++)
        {
            int v=trie[u][i];
            if(v) q.push(v),fail[v]=trie[fail[u]][i];
            else trie[u][i]=trie[fail[u]][i];
        }
    }
}
void solve()
{
    head=tail=1;
    Q.push((node){1,0});
    flag[1][0]=1;
    while(head<=tail)
    {
        node t=Q.front();
        Q.pop();
        if(t.f==(1<<n)-1)
        {
            int num=0;
            for(;head>1;head=L2[head]){ans[++num]=L1[head];}
            for(int i=num;i;i--) printf("%c",ans[i]+'A');
            return;
        }
        for(int i=0;i<26;i++)
        {
            int v=trie[t.u][i];
            int k=t.f|state[trie[t.u][i]];    
            if(flag[v][k]) continue;
            L1[++tail]=i;
            L2[tail]=head;            
            flag[v][k]=1;
            Q.push((node){v,k});
        }
        head++;
    }
}
int main()
{
    scanf("%d",&n);
    for(int i=0;i<n;i++) scanf("%s",s),add(i);
    get_fail();
    solve();
    return 0;
}

 

 

猜你喜欢

转载自www.cnblogs.com/hsez-cyx/p/12424635.html
今日推荐