BZOJ 1030 - AC自动机 + DP
2016-01-05 19:41
239 查看
1009那题仍然记忆犹新…… 首先说一下1009的拓展:如果有多个串,则需要建立AC自动机,状态也需要改成:设f[i][j]为考虑到长度为i的字符串,匹配到AC自动机的j号节点的方案数,同样地道理构造出矩阵即可,只不过这里f[i][j]为0的条件变为j号节点是单词节点。
然后看这道题,它的要求是相反的:给定一堆字符串,统计长度为m的至少包含一个给定字符串的文本串的长度。
既然要求是相反的,我们可以考虑采用补集转化的思想(值得一提的是,“包含任意一个”的问往往都可以用补集转化的思想):求不包含任何一个给定字符串的长度为m的文本串的数量。这样,就直接转化成了上面的1009拓展。设1009拓展的解为ans′,则本题的答案就是26m−ans′。
(QAQ再次参拜黄学长代码……
然后看这道题,它的要求是相反的:给定一堆字符串,统计长度为m的至少包含一个给定字符串的文本串的长度。
既然要求是相反的,我们可以考虑采用补集转化的思想(值得一提的是,“包含任意一个”的问往往都可以用补集转化的思想):求不包含任何一个给定字符串的长度为m的文本串的数量。这样,就直接转化成了上面的1009拓展。设1009拓展的解为ans′,则本题的答案就是26m−ans′。
(QAQ再次参拜黄学长代码……
// BZOJ 1030 #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int N=6000+5, L=100+5, mod=10007; #define rep(i,a,b) for (int i=a; i<=b; i++) #define dep(i,a,b) for (int i=a; i>=b; i--) #define read(x) scanf("%d", &x) #define fill(a,x) memset(a, x, sizeof(a)) int n, m, sz=1, ch [30], f , d[L] ; char st[L]; bool fail ; void insert(char *s) { int now=1, c, len=strlen(s); rep(i,0,len-1) { c=s[i]-'A'+1; if (ch[now][c]) now=ch[now][c]; else now=ch[now][c]=++sz; } fail[now]=true; } int Q[N*2]; void AC_init() { int head=0, tail=0; Q[0]=1; f[1]=0; while (head<=tail) { // BFS int x=Q[head++]; rep(i,1,26) { if (!ch[x][i]) continue; int k=f[x]; while (!ch[k][i]) k=f[k]; // 类似于KMP,从其父亲节点的f值开始往前找 f[ch[x][i]]=ch[k][i]; if (fail[ch[k][i]]) fail[ch[x][i]]=true; // 如果一个节点的失配指针指向的节点是单词节点,说明它本身也包含单词 Q[++tail]=ch[x][i]; } } } int main() { read(n); read(m); // n是单词个数,m是文本串长度 rep(i,1,26) ch[0][i]=1; // 0为Trie的根节点 fill(fail, false); rep(i,1,n) scanf("%s", st), insert(st); AC_init(); d[0][1]=1; rep(i,1,m) { rep(j,1,sz) { // 枚举第i-1位匹配到第j个节点,用以更新d[i] if (fail[j] || !d[i-1][j]) continue; // 如果一个节点包含单词或当前方案数是0,跳过 rep(k,1,26) { // 枚举第i位新添加的是字母k int p=j; while (!ch[p][k]) p=f[p]; d[i][ch[p][k]]=(d[i][ch[p][k]]+d[i-1][j])%mod; } } } int U=1, ans_=0; rep(i,1,m) U=(U*26)%mod; rep(i,1,sz) if (!fail[i]) ans_=(ans_+d[m][i])%mod; printf("%d\n", (U-ans_+mod)%mod); // 别忘了+mod防负 return 0; }
相关文章推荐
- Hadoop 下一代 MapReduce - 集群参数设置与启动
- 关于媒体查询
- C#中调用控制台程序时隐藏控制台窗口
- EXT4参数优化及测试
- Mysql 数据库学习 简单的增删改查
- iOS Mac系统下Ruby环境安装
- CCNP学习笔记17--vlan间路由
- java数据结构(1)
- T1(0860)
- redis源代码解读之内存管理————zmalloc文件
- libevent
- 正向代理与反向代理
- ios distill failed for unknow reasons解决
- 1227: [SDOI2009]虔诚的墓主人 树状数组+离散化
- 百度web-ife前端学院-task1学习笔记
- 热门地区增删城改
- HDU 5607 求A到B走K步的概率 矩阵快速幂DP
- 排序1:合并两个已排序的表
- CentOS7搭建Hadoop2.6完全分布式集群环境
- 优化UITableViewCell高度计算的那些事 附源码