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 }

 

 

posted @ 2013-08-09 09:59  silver__bullet  阅读(463)  评论(0编辑  收藏  举报