• poj 1625 Censored!


    题意:

      给你一个字典,还有一些非法串,利用字典中的字符组成长度为m的不含非法串的字符串,求方案数。

    解法:

      坑了我一整天我擦。。。。

      因为自动机本身就是一个状态转移图,所以在上面进行DP很好理解,dp[i][j]记录长度为i并且走到DFA中j节点的方案数。。

      需要注意的是非法节点是不能走的,在建Trie图的时候也要注意,如果当前节点的fail节点是非法的,那么这个点也是非法的,因为这个串包含了某个非法串。。。

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<queue>
      4 #include<map>
      5 #include<algorithm>
      6 using namespace std;
      7 const int base = 10;
      8 const int N = 105;
      9 struct BigInt{
     10     int v[N],len;
     11     BigInt(int r = 0){
     12         memset(v,0,sizeof(v));
     13         for(len = 0;r > 0;r /= base)v[len++] = r % base;
     14     }
     15     BigInt operator + (const BigInt &a){
     16         BigInt ans;int i ,c = 0;
     17         for(i = 0;i < len || i < a.len || c > 0;i++){
     18             if(i < len)c += v[i];
     19             if(i < a.len)c += a.v[i];
     20             ans.v[i] = c % base;c /= base;
     21         }
     22         ans.len = i;
     23         return ans;
     24     }
     25     void print(){
     26         printf("%d",len==0?0:v[len - 1]);
     27         for(int i = len - 2;i >= 0;i--)
     28             printf("%d",v[i]);
     29         puts("");
     30     }
     31 };
     32 BigInt dp[55][N];
     33 
     34 struct node{
     35     node *ch[55],*fail;
     36     bool flag;
     37     void clear(){
     38         for(int i = 0;i < 55;i++)ch[i] = NULL;fail = NULL;
     39         flag = 0;
     40     }
     41 };
     42 map<char,int>hash;
     43 node stk[N*6];
     44 struct Trie{
     45     node *root;int top,sz;
     46     node* newnode(){
     47         node *p = &stk[top++];
     48         p -> clear();
     49         return p;
     50     }
     51     void init(int size){
     52         top = 0;
     53         sz = size;
     54         root = newnode();
     55     }
     56     void insert(char *s){
     57         node *p = root;int len = strlen(s);
     58         for(int i = 0 ;i < len;i++){
     59             int id = hash[s[i]];
     60             if(p -> ch[id] == NULL)
     61                 p -> ch[id] = newnode();
     62             p = p -> ch[id];
     63         }
     64         p -> flag = 1;
     65     }
     66     void build(){
     67         queue<node*> Q;
     68         root -> fail = root;
     69         for(int i = 0;i < sz;i++)
     70             if(root -> ch[i] == NULL)
     71                 root -> ch[i] = root;
     72             else{
     73                 Q.push(root -> ch[i]);
     74                 root -> ch[i] -> fail = root;
     75             }
     76         while(!Q.empty()){
     77             node *p = Q.front();Q.pop();
     78             for(int i = 0;i < sz;i++)
     79                 if(p -> ch[i] == NULL)
     80                     p -> ch[i] = p -> fail -> ch[i];
     81                 else{
     82                     Q.push(p -> ch[i]);
     83                     p -> ch[i] -> fail = p -> fail -> ch[i];
     84                     p -> ch[i] -> flag |= p -> ch[i] -> fail -> flag;
     85                 }
     86         }
     87     }
     88     void solve(int len){
     89         for(int i = 0;i < 55;i++)
     90             for(int j = 0;j < top;j++)
     91                 dp[i][j] = BigInt();
     92         dp[0][root - stk] = BigInt(1);
     93         for(int i = 0;i < len;i++)
     94             for(int j = 0;j < top;j++){
     95                 node *cur = &stk[j];
     96                 if(cur -> flag)continue;
     97                 for(int k = 0;k < sz;k++){
     98                     node *next = cur -> ch[k];
     99                     if(next -> flag)continue;
    100                     dp[i+1][next - stk] = dp[i+1][next - stk] + dp[i][j];
    101                 }
    102             }
    103         BigInt ans;
    104         for(int i = 0;i < top;i++)
    105             ans = ans + dp[len][i];
    106         ans.print();
    107     }
    108 };
    109 Trie AC;
    110 char s[N];
    111 int main(){
    112     int n,m,p;
    113     while(~scanf("%d%d%d",&n,&m,&p)){
    114         scanf("%s",s);int len = strlen(s);
    115         hash.clear();
    116         for(int i = 0;i < len;i++)
    117             hash[s[i]] = i;
    118         AC.init(n);
    119         for(int i = 0;i < p;i++){
    120             scanf("%s",s);
    121             AC.insert(s);
    122         }
    123         AC.build();
    124         AC.solve(m);
    125     }
    126     return 0;
    127 }
  • 相关阅读:
    RabbitMQ指南之一:"Hello World!"
    Java8新特性之五:Optional
    Java8新特性之四:接口默认方法和静态方法
    Java8新特性之三:Stream API
    Java8新特性之二:方法引用
    Notepad++编辑器——Verilog代码片段和语法检查
    数电(5):半导体存储电路
    数电(4):组合逻辑电路
    DDR3_新版(1):IP核调取和官方例程仿真
    数电(2):逻辑代数的基本定理
  • 原文地址:https://www.cnblogs.com/silver-bullet/p/3247459.html
Copyright © 2020-2023  润新知