POJ 1625 Censored!(AC自动机+高精度+dp)

http://poj.org/problem?id=1625

题意:

给出一些单词,求长度为m的串不包含这些单词的个数。

思路:

这道题和HDU 2243和POJ 2778是一样的,不同的是这道题不取模,所以不可以用矩阵快速幂,必须使用高精度,所以这里用滚动dp解决即可。

高精度的写法参考了kuangbin巨巨的模板。

  1 #include<iostream>
  2 #include<algorithm>
  3 #include<cstring>
  4 #include<cstdio>
  5 #include<vector>
  6 #include<stack>
  7 #include<queue>
  8 #include<cmath>
  9 #include<map>
 10 #include<set>
 11 using namespace std;
 12 typedef long long ll;
 13 const int INF = 0x3f3f3f3f;
 14 const int maxn=10000+5;
 15 
 16 int n, m, num, p, len;
 17 map<char,int> mp;
 18 char s[105];
 19 
 20 struct Trie
 21 {
 22     int son[55];
 23     int cnt;
 24     int fail;
 25 }t[55*55];
 26 
 27 struct Matrix
 28 {
 29     int mat[110][110], n;
 30     Matrix(){}
 31     Matrix(int _n)
 32     {
 33         n=_n;
 34         for(int i=0;i<n;i++)
 35         for(int j=0;j<n;j++)
 36             mat[i][j]=0;
 37     }
 38 };
 39 
 40 void init(int x)
 41 {
 42     t[x].fail=0;
 43     t[x].cnt=0;
 44     memset(t[x].son,0,sizeof(t[x].son));
 45 }
 46 
 47 void trie(char *s)
 48 {
 49     int n=strlen(s);
 50     int x=0;
 51     for(int i=0;i<n;i++)
 52     {
 53         int c=mp[s[i]];
 54         if(!t[x].son[c])
 55         {
 56             num++;
 57             init(num);
 58             t[x].son[c]=num;
 59         }
 60         x=t[x].son[c];
 61     }
 62     t[x].cnt=1;
 63 }
 64 
 65 void buildAC()
 66 {
 67     queue<int> Q;
 68     for(int i=1;i<=len;i++)  if(t[0].son[i])  Q.push(t[0].son[i]);
 69     while(!Q.empty())
 70     {
 71         int x=Q.front(); Q.pop();
 72         int fail=t[x].fail;
 73         for(int i=1;i<=len;i++)
 74         {
 75 
 76             int y=t[x].son[i];
 77             if(y)
 78             {
 79                 t[y].fail=t[fail].son[i];
 80                 t[y].cnt|=t[t[fail].son[i]].cnt;  //这儿很重要,这个标记需要传递
 81                 Q.push(y);
 82             }
 83             else t[x].son[i]=t[fail].son[i];
 84         }
 85     }
 86 }
 87 
 88 Matrix getMatrix()
 89 {
 90     Matrix c=Matrix(num+1);
 91     for(int i=0;i<=num;i++)
 92     {
 93         for(int j=1;j<=len;j++)
 94         {
 95             if(t[t[i].son[j]].cnt==0)  c.mat[i][t[i].son[j]]++;
 96         }
 97     }
 98     return c;
 99 }
100 
101 /******************************高精度算法************************************/
102 struct BigInt
103 {
104     const static int mod = 10000;
105     const static int DLEN = 4;
106     int a[600],len;
107     BigInt()
108     {
109         memset(a,0,sizeof(a));
110         len = 1;
111     }
112     BigInt(int v)
113     {
114         memset(a,0,sizeof(a));
115         len = 0;
116         do
117         {
118             a[len++] = v%mod;
119             v /= mod;
120         }while(v);
121     }
122     BigInt(const char s[])
123     {
124         memset(a,0,sizeof(a));
125         int L = strlen(s);
126         len = L/DLEN;
127         if(L%DLEN)len++;
128         int index = 0;
129         for(int i = L-1;i >= 0;i -= DLEN)
130         {
131             int t = 0;
132             int k = i - DLEN + 1;
133             if(k < 0)k = 0;
134             for(int j = k;j <= i;j++)
135                 t = t*10 + s[j] - '0';
136             a[index++] = t;
137         }
138     }
139     BigInt operator +(const BigInt &b)const
140     {
141         BigInt res;
142         res.len = max(len,b.len);
143         for(int i = 0;i <= res.len;i++)
144             res.a[i] = 0;
145         for(int i = 0;i < res.len;i++)
146         {
147             res.a[i] += ((i < len)?a[i]:0)+((i < b.len)?b.a[i]:0);
148             res.a[i+1] += res.a[i]/mod;
149             res.a[i] %= mod;
150         }
151         if(res.a[res.len] > 0)res.len++;
152         return res;
153     }
154     BigInt operator *(const BigInt &b)const
155     {
156         BigInt res;
157         for(int i = 0; i < len;i++)
158         {
159             int up = 0;
160             for(int j = 0;j < b.len;j++)
161             {
162                 int temp = a[i]*b.a[j] + res.a[i+j] + up;
163                 res.a[i+j] = temp%mod;
164                 up = temp/mod;
165             }
166             if(up != 0)
167                 res.a[i + b.len] = up;
168         }
169         res.len = len + b.len;
170         while(res.a[res.len - 1] == 0 &&res.len > 1)res.len--;
171         return res;
172     }
173     void output()
174     {
175         printf("%d",a[len-1]);
176         for(int i = len-2;i >=0 ;i--)
177             printf("%04d",a[i]);
178         printf("
");
179     }
180 };
181 /*************************************************************************/
182 
183 BigInt dp[2][110];
184 
185 int main()
186 {
187     //freopen("in.txt","r",stdin);
188     scanf("%d%d%d",&n,&m,&p);
189     mp.clear();
190     scanf("%s",s+1);
191     len=strlen(s+1);
192     for(int i=1;i<=len;i++)  mp[s[i]]=i;
193     for(int i=1;i<=p;i++)
194     {
195         scanf("%s",s);
196         trie(s);
197     }
198     buildAC();
199     Matrix a=getMatrix();
200 
201     //滚动数组实现
202     int now = 0;
203     dp[now][0] = 1;
204     for(int i=0;i<a.n;i++) dp[now][i] = 0;
205     for(int i=0;i<m;i++)
206     {
207         now^=1;
208         for(int j=0;j<a.n;j++) dp[now][j] = 0;
209         for(int j=0;j<a.n;j++)
210         for(int k=0;k<a.n;k++)
211             if(a.mat[j][k] > 0) dp[now][k] = dp[now][k]+dp[now^1][j]*a.mat[j][k];
212     }
213     BigInt ans = 0;
214     for(int i = 0;i < a.n;i++)
215         ans = ans + dp[now][i];
216     ans.output();
217     return 0;
218 }
原文地址:https://www.cnblogs.com/zyb993963526/p/7447006.html