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("\n"); 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 }