bzoj 1030 ac自动机

  比较容易看出来先建立ac自动机,然后在自动机上做DP,设w[0..1][i][j]为当前不包括/包括字典中的字符串,当前在自动机中走到第i个节点,完成的文本的长度为j的方案数,那么比较容易的转移w[i|j->child->cnt][j->child][k+1]+=w[i][j][k]。

  

/**************************************************************
    Problem: 1030
    User: BLADEVIL
    Language: C++
    Result: Accepted
    Time:200 ms
    Memory:25596 kb
****************************************************************/
 
//By BLADEVIL
#include <cstdio>
#include <cstring>
#define maxn 10010
#define maxm 200
#define d39 10007
 
using namespace std;
 
int n,m;
int w[3][maxm][maxn];
 
struct node{
    int cnt,num;
    node *child[30],*fail;
    node (){
        cnt=num=0;
        memset(child,0,sizeof child);
        fail=NULL;
    }
} nodepool[maxn],*totnode,*root,*que[maxn];
 
void build_trie(){
    totnode=nodepool; root=totnode++;
    for (int i=1;i<=n;i++){
        char c[maxm];
        scanf("%s",&c);
        int len=strlen(c);
        node *t=root;
        for (int j=0;j<len;j++){
            if (!t->child[c[j]-'A']) t->child[c[j]-'A']=totnode++;
            t=t->child[c[j]-'A'];
        }
        t->cnt=1;
    }
}
 
void build_ac(){
    int h=0,t=1;
    que[1]=root; root->fail=root; 
    for (int i=0;i<26;i++) if (!root->child[i])   root->child[i]=root;
    while (h<t){
        node *u=que[++h];
        for (int i=0;i<26;i++) if (u->child[i]&&u->child[i]!=root){
            que[++t]=u->child[i];
            que[t]->fail=u->fail->child[i]!=que[t]?u->fail->child[i]:root;
            que[t]->cnt|=que[t]->fail->cnt;
        } else u->child[i]=u->fail->child[i];
    }
}
 
void dp(){
    int j=1;
    for (node *i=nodepool;i!=totnode;i++) i->num=j++;
//for (node *i=nodepool;i!=totnode;i++) printf("%d %d %d\n",i->cnt,i->num,i->fail->num);
    w[0][1][1]=1;
    for (int t=0;t<2;t++)
        for (int i=1;i<=m;i++)
            for (node *j=nodepool;j!=totnode;j++)
                if (w[t][i][j->num])
                    for (int k=0;k<26;k++)
                        (w[t|j->child[k]->cnt][i+1][j->child[k]->num]+=w[t][i][j->num])%=d39;
    int ans=0;
    for (node *i=nodepool;i!=totnode;i++)
        (ans+=w[1][m+1][i->num])%=d39;
    printf("%d\n",ans);
}
 
int main(){
    scanf("%d%d",&n,&m);
    build_trie();
    build_ac();
    dp();
    return 0;
}

 

  

posted on 2014-03-06 08:51  BLADEVIL  阅读(506)  评论(0编辑  收藏