BZOJ 1195: [HNOI2006]最短母串 AC自动机+状压+搜索

思路比较直接. 

由于 $n$ 很小,直接定义 $f[i][j]$ 表示当前在自动机中的节点 $i,$ 被覆盖串的集合为 $j$ 的方案数.   

#include <bits/stdc++.h>  
#define N 750
#define M 150000 
#define setIO(s) freopen(s".in","r",stdin) , freopen(s".out","w",stdout)    
using namespace std;  
int n,tot,edges,kk;     
int Log[30],hd[N],to[N],nex[N],mark[N][5000],fa[M*10],C[M*10];      
char str[N];   
queue<int>q;  
struct Sta 
{ 
    int u,sta,id;  
    Sta(int u=0,int sta=0,int id=0):u(u),sta(sta),id(id){}      
};         
queue<Sta>Q;   
struct Node  
{
    int sta,f,tag,ch[27];  
}t[N];            
void add(int u,int v) 
{
    nex[++edges]=hd[u],hd[u]=edges,to[edges]=v;   
}      
void insert(int xx) 
{ 
    int p=0,i,j,len=strlen(str+1);    
    for(i=1;i<=len;++i) 
    {
        int c=str[i]-'A'; 
        if(!t[p].ch[c]) t[p].ch[c]=++tot;    
        p=t[p].ch[c];    
    } 
    t[p].tag=1;   
    t[p].sta|=Log[xx];   
}   
void build() 
{ 
    int i,j; 
    for(i=0;i<27;++i) if(t[0].ch[i]) q.push(t[0].ch[i]),add(0,t[0].ch[i]);   
    for(;!q.empty();) 
    {
        int u=q.front();q.pop();   
        for(i=0;i<27;++i) 
        {
            int qq=t[u].ch[i];    
            if(!qq) 
            {
                t[u].ch[i]=t[t[u].f].ch[i];  
                continue;   
            } 
            t[qq].f=t[t[u].f].ch[i];         
            add(t[qq].f,qq);   
            q.push(qq);  
        }
    }
} 
// 继承自己.    
void dfs(int x) 
{
    for(int i=hd[x];i;i=nex[i]) 
    {
        int v=to[i];  
        t[v].sta|=t[x].sta; 
        dfs(v);          
    }  
}   
void print(int c) 
{ 
    if(C[c]==-1) return;    
    print(fa[c]);   
    printf("%c",C[c]+'A');    
}
int main() 
{ 
    int i,j; 
    scanf("%d",&n);  
    for(i=1;i<=14;++i) Log[i]=(1<<(i-1));   
    for(i=1;i<=n;++i) scanf("%s",str+1),insert(i);   
    build(),dfs(0),C[0]=-1;                     
    for(Q.push(Sta(0,0,kk)),mark[0][0]=1;!Q.empty();) 
    {
        Sta e=Q.front(); Q.pop();       
        if(e.sta==Log[n+1]-1)     
        {   
            print(e.id);   
            return 0;    
        }    
        int v;    
        int u=e.u; 
        int idx=e.id;    
        int sta=e.sta;   
        for(i=0;i<27;++i) 
        {    
            v=t[u].ch[i];  
            if(!v) continue;        
            if(mark[v][sta|t[v].sta]) 
            {
                continue;  
            }
            ++kk; 
            fa[kk]=idx;              
            C[kk]=i;    
            mark[v][sta|t[v].sta]=1;          
            Q.push(Sta(v,(sta|t[v].sta),kk));               
        }
    }
    return 0;        
}