zoukankan      html  css  js  c++  java
  • BZOJ1030 [JSOI2007]文本生成器[DP+AC自动机]

    我学到现在才是初三学弟的水平。。哭

    这里相当于求长度为$m$的,字符集${A...Z}$的且不包含任一模式串的文本串个数。这是一个典型的AC自动机匹配计数问题。

    设$f_{i,j}$表示在AC自动机上面走了$i$步在$j$点的方案数。

    注意由于不能包含任一模式串,也就是说任意时刻都不能项后缀含有模式串的点上走,也就是fail树上所有以模式串结尾点为根的子树上的点。

    这个可以在建立fail树的时候附带标记好。

    于是转移的时候枚举字符集,下一步可以走向合法节点则转移之,否则不转移。边界$f_{0,0}=1$。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<cmath>
     6 #include<queue>
     7 #define dbg(x) cerr << #x << " = " << x <<endl
     8 using namespace std;
     9 typedef long long ll;
    10 typedef double db;
    11 typedef pair<int,int> pii;
    12 template<typename T>inline T _min(T A,T B){return A<B?A:B;}
    13 template<typename T>inline T _max(T A,T B){return A>B?A:B;}
    14 template<typename T>inline char MIN(T&A,T B){return A>B?(A=B,1):0;}
    15 template<typename T>inline char MAX(T&A,T B){return A<B?(A=B,1):0;}
    16 template<typename T>inline void _swap(T&A,T&B){A^=B^=A^=B;}
    17 template<typename T>inline T read(T&x){
    18     x=0;int f=0;char c;while(!isdigit(c=getchar()))if(c=='-')f=1;
    19     while(isdigit(c))x=x*10+(c&15),c=getchar();return f?x=-x:x;
    20 }
    21 const int P=10007,N=6000+7;
    22 char s[100+7];
    23 int tr[N][26],nxt[N],ban[N],bin[N],tot,cnt;
    24 int f[100+7][N];
    25 int n,m,ans;
    26 inline void Insert(){
    27     int len=strlen(s+1),x=0;
    28     for(register int i=1,c=s[1]-'A';i<=len;++i,c=s[i]-'A'){
    29         if(!tr[x][c])tr[x][c]=++tot;
    30         x=tr[x][c];
    31     }
    32     ban[x]=1;
    33 }
    34 queue<int> q;
    35 inline void Build(){
    36     bin[cnt=1]=0;
    37     for(register int i=0;i<26;++i)if(tr[0][i])nxt[tr[0][i]]=0,q.push(tr[0][i]);
    38     while(!q.empty()){
    39         int x=q.front();q.pop();
    40         if(ban[nxt[x]])ban[x]=1;
    41         if(!ban[x])bin[++cnt]=x;
    42         for(register int i=0;i<26;++i){
    43             if(tr[x][i])nxt[tr[x][i]]=tr[nxt[x]][i],q.push(tr[x][i]);
    44             else tr[x][i]=tr[nxt[x]][i];
    45         }
    46     }
    47 }
    48 inline void add(int&A,int B){A+=B;A>=P&&(A-=P);}
    49 inline int fpow(int x,int p){int ret=1;for(;p;p>>=1,x=x*x%P)if(p&1)ret=ret*x%P;return ret;}
    50 inline void dp(){
    51     f[0][0]=1;
    52     for(register int i=0;i<m;++i)
    53         for(register int j=1;j<=cnt;++j)if(f[i][bin[j]])
    54             for(register int k=0;k<26;++k)if(!ban[tr[bin[j]][k]])
    55                 add(f[i+1][tr[bin[j]][k]],f[i][bin[j]]);
    56 }
    57 
    58 int main(){//freopen("test.in","r",stdin);//freopen("test.ans","w",stdout);
    59     read(n),read(m);
    60     for(register int i=1;i<=n;++i)scanf("%s",s+1),Insert();
    61     Build();
    62     dp();
    63     for(register int i=1;i<=cnt;++i)add(ans,f[m][bin[i]]);
    64     printf("%d
    ",(fpow(26,m)-ans+P)%P);
    65     return 0;
    66 }
    View Code

    这里使用AC自动机位置描述状态,是为了有效满足合法性。注意。

  • 相关阅读:
    windows下编译php7图形库php_ui.dll
    php 图形用户界面GUI 开发
    使用PHPStorm 配置自定义的Apache与PHP环境
    公用代码实现两个表的拼接(部分代码)
    WCF学习心得--客户端获取服务端自定义类数据
    动态规划入门——Eddy's research II
    linux route命令学习
    软件度量都该度个啥?(5)——被吹得最多的六西格玛
    VSS的运用小内容(针对于vs2008版本)(小的问题都是,仅供参考--只针对于菜鸟级的)
    cocos2d-x学习日志(13) --A星寻路算法demo
  • 原文地址:https://www.cnblogs.com/saigyouji-yuyuko/p/11558177.html
Copyright © 2011-2022 走看看