Censored! POJ - 1625 AC自动机+大数DP
题意:
给出一n种字符的字典,有p个禁用的单词,
问能组成多少个不同的长度为m的合法字符串。(m<=50)
题解:
是不是个我们之前做的题目非常非常像,题意都一样。
直接将上次写的AC自动机+矩阵快速幂的代码交上去。
然后突然发现没有取模,好像直接炸了。即便只有50,但是方案数还是爆__int128了
处理不了,这题还是必须用大数的。
p<=10 我们可以考虑状压实现。
这题还是和之前的题目有点关系的,需要求出可达矩阵,然后根据这个去DP
dp[i][j] 表示第 i 步 在AC自动机 j 这个节点 的方案数目,
然后第 i 步只跟 第 i - 1步的状态有关,然后可以滚动掉这一维。
不用试不滚动的了,会mle的。 别问我怎么知道的!!!!
1 #include <set> 2 #include <map> 3 #include <stack> 4 #include <queue> 5 #include <cmath> 6 #include <cstdio> 7 #include <string> 8 #include <vector> 9 #include <time.h> 10 #include <cstring> 11 #include <iostream> 12 #include <algorithm> 13 14 #define pi acos(-1.0) 15 #define eps 1e-9 16 #define fi first 17 #define se second 18 #define rtl rt<<1 19 #define rtr rt<<1|1 20 #define bug printf("******\n") 21 #define mem(a, b) memset(a,b,sizeof(a)) 22 #define name2str(x) #x 23 #define fuck(x) cout<<#x" = "<<x<<endl 24 #define sf(n) scanf("%d", &n) 25 #define sff(a, b) scanf("%d %d", &a, &b) 26 #define sfff(a, b, c) scanf("%d %d %d", &a, &b, &c) 27 #define sffff(a, b, c, d) scanf("%d %d %d %d", &a, &b, &c, &d) 28 #define pf printf 29 #define FIN freopen("../date.txt","r",stdin) 30 #define gcd(a, b) __gcd(a,b) 31 #define lowbit(x) x&-x 32 #define IO iOS::sync_with_stdio(false) 33 34 35 using namespace std; 36 typedef long long LL; 37 typedef unsigned long long ULL; 38 const int maxn = 1e6 + 7; 39 const int maxm = 8e6 + 10; 40 const int INF = 0x3f3f3f3f; 41 const int mod = 1e9 + 7; 42 43 struct Matrix { 44 int mat[110][110], n; 45 46 Matrix() {} 47 48 Matrix(int _n) { 49 n = _n; 50 for (int i = 0; i < n; i++) 51 for (int j = 0; j < n; j++) 52 mat[i][j] = 0; 53 } 54 55 Matrix operator*(const Matrix &b) const { 56 Matrix ret = Matrix(n); 57 for (int i = 0; i < n; i++) 58 for (int j = 0; j < n; j++) 59 for (int k = 0; k < n; k++) { 60 int tmp = (long long) mat[i][k] * b.mat[k][j] % mod; 61 ret.mat[i][j] = (ret.mat[i][j] + tmp) % mod; 62 } 63 return ret; 64 } 65 }; 66 67 68 char buf[1000010]; 69 int n, m, p; 70 map<char, int> mp; 71 72 struct Aho_Corasick { 73 int next[110][52], fail[110], End[110]; 74 int root, cnt; 75 76 int newnode() { 77 for (int i = 0; i < 52; i++) next[cnt][i] = -1; 78 End[cnt++] = 0; 79 return cnt - 1; 80 } 81 82 void init() { 83 cnt = 0; 84 root = newnode(); 85 } 86 87 void insert(char buf[]) { 88 int len = strlen(buf); 89 int now = root; 90 for (int i = 0; i < len; i++) { 91 if (next[now][mp[buf[i]]] == -1) next[now][mp[buf[i]]] = newnode(); 92 now = next[now][mp[buf[i]]]; 93 } 94 End[now]++; 95 } 96 97 void build() { 98 queue<int> Q; 99 fail[root] = root; 100 for (int i = 0; i < 52; i++) 101 if (next[root][i] == -1) next[root][i] = root; 102 else { 103 fail[next[root][i]] = root; 104 Q.push(next[root][i]); 105 } 106 while (!Q.empty()) { 107 int now = Q.front(); 108 Q.pop(); 109 if (End[fail[now]]) End[now] = 1; 110 for (int i = 0; i < 52; i++) 111 if (next[now][i] == -1) next[now][i] = next[fail[now]][i]; 112 else { 113 fail[next[now][i]] = next[fail[now]][i]; 114 Q.push(next[now][i]); 115 } 116 } 117 } 118 119 Matrix get_Matrix() { 120 Matrix ret = Matrix(cnt); 121 for (int i = 0; i < cnt; ++i) { 122 for (int j = 0; j < n; ++j) { 123 if (!End[next[i][j]]) ret.mat[i][next[i][j]]++; 124 } 125 } 126 return ret; 127 } 128 129 void debug() { 130 for (int i = 0; i < cnt; i++) { 131 printf("id = %3d,fail = %3d,end = %3d,chi = [", i, fail[i], End[i]); 132 for (int j = 0; j < 26; j++) printf("%2d", next[i][j]); 133 printf("]\n"); 134 } 135 } 136 } ac; 137 138 const int MAXL = 2500; 139 const int MAXN = 9999; 140 const int DLEN = 4; 141 142 class Big { 143 public: 144 int a[600], len; 145 146 Big(const int b = 0) { 147 int c, d = b; 148 len = 0; 149 memset(a, 0, sizeof(a)); 150 while (d > MAXN) { 151 c = d - (d / (MAXN + 1)) * (MAXN + 1); 152 d = d / (MAXN + 1); 153 a[len++] = c; 154 } 155 a[len++] = d; 156 } 157 158 Big(const char *s) { 159 int t, k, index, L; 160 memset(a, 0, sizeof(a)); 161 L = strlen(s); 162 len = L / DLEN; 163 if (L % DLEN) len++; 164 index = 0; 165 for (int i = L - 1; i >= 0; i -= DLEN) { 166 t = 0; 167 k = i - DLEN + 1; 168 if (k < 0) k = 0; 169 for (int j = k; j <= i; j++) t = t * 10 + s[j] - '0'; 170 a[index++] = t; 171 } 172 } 173 174 Big operator/(const LL &b) const { 175 Big ret; 176 LL down = 0; 177 for (int i = len - 1; i >= 0; i--) { 178 ret.a[i] = (a[i] + down * (MAXN + 1)) / b; 179 down = a[i] + down * (MAXN + 1) - ret.a[i] * b; 180 } 181 ret.len = len; 182 while (ret.a[ret.len - 1] == 0 && ret.len > 1) ret.len--; 183 return ret; 184 } 185 186 bool operator>(const Big &T) const { 187 int ln; 188 if (len > T.len) return true; 189 else if (len == T.len) { 190 ln = len - 1; 191 while (a[ln] == T.a[ln] && ln >= 0) ln--; 192 if (ln >= 0 && a[ln] > T.a[ln]) return true; 193 else return false; 194 } else return false; 195 } 196 197 Big operator+(const Big &T) const { 198 Big t(*this); 199 int big = T.len > len ? T.len : len; 200 for (int i = 0; i < big; i++) { 201 t.a[i] += T.a[i]; 202 if (t.a[i] > MAXN) { 203 t.a[i + 1]++; 204 t.a[i] -= MAXN + 1; 205 } 206 } 207 if (t.a[big] != 0) t.len = big + 1; 208 else t.len = big; 209 return t; 210 } 211 212 Big operator-(const Big &T) const { 213 int big; 214 bool flag; 215 Big t1, t2; 216 if (*this > T) { 217 t1 = *this; 218 t2 = T; 219 flag = 0; 220 } else { 221 t1 = T; 222 t2 = *this; 223 flag = 1; 224 } 225 big = t1.len; 226 for (int i = 0; i < big; i++) { 227 if (t1.a[i] < t2.a[i]) { 228 int j = i + 1; 229 while (t1.a[j] == 0) j++; 230 t1.a[j--]--; 231 while (j > i) t1.a[j--] += MAXN; 232 t1.a[i] += MAXN + 1 - t2.a[i]; 233 } else t1.a[i] -= t2.a[i]; 234 } 235 t1.len = big; 236 while (t1.a[t1.len - 1] == 0 && t1.len > 1) { 237 t1.len--; 238 big--; 239 } 240 if (flag) t1.a[big - 1] = 0 - t1.a[big - 1]; 241 return t1; 242 } 243 244 LL operator%(const int &b) const { 245 LL d = 0; 246 for (int i = len - 1; i >= 0; i--) d = ((d * (MAXN + 1)) % b + a[i]) % b; 247 return d; 248 } 249 250 Big operator*(const Big &T) const { 251 Big ret; 252 int i, j, up, temp, temp1; 253 for (i = 0; i < len; i++) { 254 up = 0; 255 for (j = 0; j < T.len; j++) { 256 temp = a[i] * T.a[j] + ret.a[i + j] + up; 257 if (temp > MAXN) { 258 temp1 = temp - temp / (MAXN + 1) * (MAXN + 1); 259 up = temp / (MAXN + 1); 260 ret.a[i + j] = temp1; 261 } else { 262 up = 0; 263 ret.a[i + j] = temp; 264 } 265 } 266 if (up != 0) ret.a[i + j] = up; 267 } 268 ret.len = i + j; 269 while (ret.a[ret.len - 1] == 0 && ret.len > 1) ret.len--; 270 return ret; 271 } 272 273 void print() { 274 printf("%d", a[len - 1]); 275 for (int i = len - 2; i >= 0; i--) printf("%04d", a[i]); 276 } 277 }; 278 279 Big dp[2][105]; 280 281 int main() { 282 //FIN; 283 while (~scanf("%d%d%d", &n, &m, &p)) { 284 mp.clear(); 285 scanf("%s", buf); 286 int len = strlen(buf); 287 for (int i = 0; i < len; ++i) mp[buf[i]] = i; 288 ac.init(); 289 for (int i = 0; i < p; ++i) { 290 scanf("%s", buf); 291 ac.insert(buf); 292 } 293 ac.build(); 294 Matrix mat = ac.get_Matrix(); 295 // for (int i = 0; i < mat.n; ++i) { 296 // for (int j = 0; j < mat.n; ++j) { 297 // printf("%d ",mat.mat[i][j]); 298 // } 299 // printf("\n"); 300 // } 301 int now=0; 302 dp[now][0] = 1; 303 for (int i = 1; i < mat.n; ++i) dp[now][i] = 0; 304 for (int i = 1; i <= m; ++i) { 305 now^=1; 306 for (int j = 0; j < mat.n; ++j) dp[now][j]=0; 307 for (int j = 0; j < mat.n; ++j) { 308 for (int k = 0; k < mat.n; ++k) { 309 if (mat.mat[j][k]) dp[now][k] = dp[now][k] + dp[now^1][j] * mat.mat[j][k]; 310 } 311 } 312 } 313 Big ans = 0; 314 for (int i = 0; i < mat.n; ++i) ans = ans + dp[now][i]; 315 ans.print(); 316 printf("\n"); 317 } 318 return 0; 319 }
View Code
转载于:https://www.cnblogs.com/qldabiaoge/p/11376043.html
Censored! POJ - 1625 AC自动机+大数DP相关推荐
- Censored! POJ - 1625
Censored! POJ - 1625 ac自动机 + 高精度 + dp 1 #include <iostream> 2 #include <queue> 3 #includ ...
- POJ 1625 Censored! (AC自动机 + 高精度 + DP)
题目链接:Censored! 解析:AC自动机 + 高精度 + 简单DP. 字符有可能会超过128,用map映射一下即可. 中间的数太大,得上高精度. 用矩阵快速幂会超时,简单的DP就能解决时间的问题 ...
- 【HDU3530】 [Sdoi2014]数数 (AC自动机+数位DP)
3530: [Sdoi2014]数数 Time Limit: 10 Sec Memory Limit: 512 MB Submit: 682 Solved: 364 Description 我们称 ...
- 【bzoj3530】[Sdoi2014]数数 AC自动机+数位dp
题目描述 我们称一个正整数N是幸运数,当且仅当它的十进制表示中不包含数字串集合S中任意一个元素作为其子串.例如当S=(22,333,0233)时,233是幸运数,2333.20233.3223不是幸运 ...
- 【BZOJ3530】数数(SDOI2014)-AC自动机+数位DP
测试地址:数数 做法:本题需要用到AC自动机+数位DP. 首先看到多模式串匹配,自然想到用AC自动机来做.用AC自动机构造出状态转移图后,令f(i,j,k)f(i,j,k)f(i,j,k)为匹配了最高 ...
- Censored! POJ - 1625(AC自动机 + dp +高精度模板)
题目链接 题目大意:给你一个字母表,给定一些敏感字符串,问长度为m且不含任意敏感字符串的串有多少个.(字符全部来自字母表) 思路:首先第一个坑点是输入的字符是unsigned char,可能出现负的A ...
- AC自动机 + 概率dp + 高斯消元 --- HDU 5955 or 2016年沈阳icpc H [AC自动机 + 概率dp + 高斯消元]详解
题目链接 题目大意: 就是有NNN个人,每个人都会猜一个长度为LLL的只包含{1,2,3,4,5,6}\{1,2,3,4,5,6\}{1,2,3,4,5,6}的序列,现在裁判开始投掷骰子,并且把每次的 ...
- ZOJ-3494 BCD Code (ac自动机+数位dp)
题目链接 Problem Description Binary-coded decimal (BCD) is an encoding for decimal numbers in which each ...
- HDU3247 Resource Archiver(AC自动机+BFS+DP)
题目,求最短的包含所有n个DNA片段且不包含任何一个病毒片段的序列. 容易用所有DNA片段和病毒片段建一个AC自动机,构造fail时处理一下各个结点后缀是DNA或者病毒的情况,然后dp[S][u]表示 ...
最新文章
- Jürgen Schmidhuber回顾30年前旧作,称其启发了现今流行的很多概念
- golang 读取文件
- 云计算被视为继计算机,8+第八章+计算机网络技术分析.ppt
- Reveal使用心法
- centos xampp安装mysql_在xampp上部署dvwa|centos(linux)环境
- JavaFX UI控件教程(二十三)之Menu
- MySQL left()函数
- c++将.cpp编译为.so文件
- 放弃高考“打游戏”,别人25岁年入百万、我退役后回家修车
- 【Docker】WARNING: Published ports are discarded when using host network mode
- QT每日一练day11:QMainWindow
- 公司因为薪资问题,走了一个各方面都不错的老工人,花更多的钱招来一个跨行业新手,这是为什么?
- [译] JavaScript 的函数式编程是一种反模式
- Checkstyle的配置集
- 第一个ExtJS练习(添加用户面板)
- 最新 Python 爬虫利器!
- 在Spinnaker中创建微服务部署管道
- WINDOWS XP优化批处理
- VRP基础,命令行基础,文件系统基础,系统管理(2017年12月13日 09:51:51)
- 组装一台台式计算机的流程,如何组装电脑?组装电脑的操作流程!