博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
poj2778(AC 自动机)
阅读量:7259 次
发布时间:2019-06-29

本文共 3111 字,大约阅读时间需要 10 分钟。

题意

构造只包含 \(A, T, C, G\) 的字符串,且满足不出现指定的一些字符串,问长度为 \(n\) 的字符串有多少种 ?

分析

AC 自动机 + 矩阵快速幂的神题 ,知识点很多。。。

AC 自动机为了给不同的状态之间建边,矩阵快速幂是为了加速状态转移。

比如说一共有 \(5\) 个状态,我要从 状态 \(0\) 转移到 状态 \(4\) ,从 \(0\) 出发,可以先转移到 \(0\) 再转移到 \(4\) ,也可以先转移到 \(1\) 再转移到 \(4\) ,后面类似。

建一个邻接矩阵,\(mat[i][j]\) 表示 \(i\) 转移到 \(j\) 的方案数,想象一下矩阵相乘的情况,\(mat[0][4]\) 的计算过程,神奇。。。

code

#include
#include
#include
#include
using namespace std;typedef long long ll;const int MAXN = 105;const int MOD = 1e5;int n, m;struct Matrix { ll mat[MAXN][MAXN]; void init() { memset(mat, 0, sizeof mat); }};Matrix operator*(Matrix A, Matrix B) { Matrix C; C.init(); for(int i = 0; i < n; i++) { for(int j = 0; j < n; j++) { for(int k = 0; k < n; k++) { C.mat[i][j] = (C.mat[i][j] + A.mat[i][k] * B.mat[k][j]) % MOD; } } } return C;}Matrix operator^(Matrix A, int x) { Matrix B; B.init(); for(int i = 0; i < n; i++) B.mat[i][i] = 1; while(x) { if(x & 1) B = B * A; A = A * A; x >>= 1; } return B;}struct Trie { int id[100]; int root, L, nxt[MAXN][4], val[MAXN], fail[MAXN]; int newnode() { for(int i = 0; i < 4; i++) { nxt[L][i] = -1; } return L++; } void init() { id['A'] = 0; id['T'] = 1; id['C'] = 2; id['G'] = 3; L = 0; root = newnode(); memset(val, 0, sizeof val); } void insert(char s[15]) { int len = strlen(s); int now = root; for(int i = 0; i < len; i++) { int d = id[s[i]]; if(nxt[now][d] == -1) nxt[now][d] = newnode(); now = nxt[now][d]; } val[now] = 1; } void build() { queue
Q; for(int i = 0; i < 4; i++) { if(nxt[root][i] == -1) nxt[root][i] = root; else { fail[nxt[root][i]] = root; Q.push(nxt[root][i]); } } while(!Q.empty()) { int now = Q.front(); Q.pop(); if(val[fail[now]]) val[now] = 1; for(int i = 0; i < 4; i++) { if(nxt[now][i] == -1) nxt[now][i] = nxt[fail[now]][i]; else { fail[nxt[now][i]] = nxt[fail[now]][i]; Q.push(nxt[now][i]); } } } } Matrix buildMatrix() { Matrix A; A.init(); for(int i = 0; i < L; i++) { for(int j = 0; j < 4; j++) { if(!val[i] && !val[nxt[i][j]]) { A.mat[i][nxt[i][j]]++; } } } return A; }}trie;int main() { trie.init(); int k; scanf("%d%d", &m, &k); for(int i = 0; i < m; i++) { char s[15]; scanf("%s", s); trie.insert(s); } trie.build(); Matrix A = trie.buildMatrix(); n = trie.L; A = A ^ k; int ans = 0; for(int i = 0; i < n; i++) { ans = (ans + A.mat[0][i]) % MOD; } printf("%d\n", ans); return 0;}

转载于:https://www.cnblogs.com/ftae/p/7327971.html

你可能感兴趣的文章
Eclipse上GIT插件EGIT使用手册之二_使用EGIT前的配置
查看>>
AppExchange Partner Keynote
查看>>
MySQL 常用语法 之 UNION与UNION ALL
查看>>
boost::thread用法
查看>>
【转】iPhone屏幕尺寸、分辨率及适配
查看>>
ubuntu下phpstorm无法输入中文的解决办法
查看>>
mysql无密码重启
查看>>
js之事件冒泡和事件捕获(四)
查看>>
获得MFC窗口指针方法总结
查看>>
[PAL算法说明]SAP HANA PAL线性回归预测分析Linear Regression算法说明LRREGRESSION
查看>>
经典SQL语句大全
查看>>
ASP.NET版Memcached监控工具(转载)
查看>>
winform treeView 数据绑定
查看>>
Java网络编程之查找Internet地址
查看>>
spark1.4配置安装
查看>>
JAVA学习课第二十八届(多线程(七))- 停止-threaded多-threaded面试题
查看>>
oracle修改表空间
查看>>
Flash Builder中“Error: #2036 加载未完成”错误的解决方法
查看>>
PR&AE插件开发遇到的一个坑
查看>>
Android仿微信图片上传,可以选择多张图片,缩放预览,拍照上传等
查看>>