首页 > 代码库 > poj1625Censored!(AC自动机+dp)

poj1625Censored!(AC自动机+dp)

链接

第一次做这种题目,参考了下题解,相当于把树扯直了做DP,估计这一类题都是这个套路吧。

状态方程dp[i][next] = dp[i][next]+dp[i][j] ;dp[i][j]表示长度为i的第J个结点的时候满足题意的num,next为当前j点所能走到的下一个合法的结点。

需要用高精度,看到一些规范的高精度写法,觉得不错,有空整理下来。

不知道是不是我理解错了,按理说字符串病毒长度不应超过10.。但开到55依旧RE,开550AC。。。

  1 #include <iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<stdlib.h>
  6 #include<vector>
  7 #include<cmath>
  8 #include<queue>
  9 #include<set>
 10 using namespace std;
 11 #define N 110
 12 #define LL long long
 13 #define INF 0xfffffff
 14 const double eps = 1e-8;
 15 const double pi = acos(-1.0);
 16 const double inf = ~0u>>2;
 17 const int child_num = 110;
 18 const int BASE = 10000;
 19 const int DIG = 4;
 20 char s[N*100],vir[550];
 21 int id[2024];
 22 struct bignum
 23 {
 24      int a[110],len;
 25      bignum()
 26      {
 27          memset(a,0,sizeof(a));
 28          len = 1;
 29      }
 30      bignum(int v)
 31      {
 32          memset(a,0,sizeof(a));
 33          len = 0;
 34          do
 35          {
 36              a[len++] = v%BASE;
 37              v/=BASE;
 38          }while(v);
 39      }
 40      /*bignum(const char s[])
 41      {
 42          memset(a,0,sizeof(a));
 43          int k = strlen(s);
 44          len = k/DIG;
 45          if(k%DIG) len++;
 46          int cnt = 0;
 47          for(int i = k-1;  i >= 0 ; i-=DIG)
 48          {
 49              int t = 0;
 50              int kk = i-DIG+1;
 51              if(kk<0) kk =0;
 52              for(int j = kk ; j <= i ; j++)
 53              t = t*10+s[j]-‘0‘;
 54              a[cnt++] = t;
 55          }
 56      }*/
 57      bignum operator + (const bignum &b)const
 58      {
 59          bignum res;
 60          res.len = max(len,b.len);
 61          int i;
 62          for(i = 0 ; i < res.len ;i ++)
 63          res.a[i] = 0;
 64          for(i = 0 ; i < res.len ; i++)
 65          {
 66              res.a[i] += ((i<len)?a[i]:0)+((i<b.len)?b.a[i]:0);
 67              res.a[i+1] += res.a[i]/BASE;
 68              res.a[i] = res.a[i]%BASE;
 69          }
 70          if(res.a[res.len]>0) res.len++;
 71          return res;
 72      }
 73      void output()
 74      {
 75          printf("%d",a[len-1]);
 76          for(int i = len-2 ; i >=0 ; i--)
 77          printf("%04d",a[i]);
 78          printf("\n");
 79      }
 80 }dp[110][110];
 81 class AC
 82 {
 83     private:
 84     int ch[N][child_num];
 85     int Q[N];
 86     int val[N];
 87     int fail[N];
 88     //int id[N];
 89     int sz;
 90     public :
 91     void init()
 92     {
 93         fail[0] = 0;
 94         //for(int i = 0 ;i < child_num-32 ; i++)
 95         //id[i+32] = i;
 96     }
 97     void reset()
 98     {
 99         memset(val,0,sizeof(val));
100         memset(fail,0,sizeof(fail));
101         memset(ch[0],0,sizeof(ch[0]));
102         sz = 1;
103     }
104     void insert(char *a,int key)
105     {
106         int k = strlen(a),p = 0;
107         for(int i = 0 ; i < k ;i++)
108         {
109             int d = id[a[i]];
110             if(ch[p][d]==0)
111             {
112                 memset(ch[sz],0,sizeof(ch[sz]));
113                 ch[p][d] = sz++;
114             }
115             p = ch[p][d];
116         }
117         val[p] = key;
118     }
119     void construct(int n)
120     {
121         int i,head=0,tail = 0;
122         for(i = 0; i < n ; i++)
123         {
124             if(ch[0][i])
125             {
126                 Q[tail++] = ch[0][i];
127                 fail[ch[0][i]] = 0;
128             }
129         }
130         while(head!=tail)
131         {
132             int u = Q[head++];
133             val[u]|=val[fail[u]];
134             for(i = 0 ; i < n ; i++)
135             {
136                 if(ch[u][i])
137                 {
138                     Q[tail++] = ch[u][i];
139                     fail[ch[u][i]] = ch[fail[u]][i];
140                 }
141                 else ch[u][i] = ch[fail[u]][i];
142             }
143         }
144     }
145     void work(int m,int n)
146     {
147         int i,j,g;
148         for(i = 1; i <= m ;i++)
149             for(j = 0 ;j <= sz; j++)
150             dp[i][j] = bignum(0);
151         dp[0][0] = bignum(1);
152         for(i = 0 ; i < m ;i++)
153         {
154             for(j = 0 ; j < sz ;j++)
155             for(g = 0 ; g < n ; g++)
156             if(!val[ch[j][g]])
157             {
158                 dp[i+1][ch[j][g]]=dp[i+1][ch[j][g]]+dp[i][j];
159             }
160         }
161         bignum ans = bignum(0);
162         for(j = 0 ;j < sz ; j++)
163         ans=ans+dp[m][j];
164         ans.output();
165     }
166 }ac;
167 int main()
168 {
169     int n,m,i,p;
170     ac.init();
171     while(cin>>n>>m>>p)
172     {
173         cin>>s;
174         for(i = 0 ; i < n; i++)
175         id[s[i]] = i;
176         ac.reset();
177         for(i = 1;i <= p; i++)
178         {
179             scanf("%s",vir);
180             ac.insert(vir,1);
181         }
182         ac.construct(n);
183         ac.work(m,n);
184     }
185     return 0;
186 }
View Code