POJ 2778 (AC自动机 矩阵快速幂)
来源:互联网 发布:阿里云域名备案服务号 编辑:程序博客网 时间:2024/06/06 10:07
题目链接:点击这里
题意:求不出现任意一个模式串的长度为m的文本串的数量.
建立AC自动机,文本串生成的过程可以看成是在自动机上某一个节点往4个方向上走一步,因为不能出现模式串,所以不能走到模式串结尾的节点.所以可以建立矩阵,a[i][j] 表示从节点i到节点j的方案数. 根据邻接矩阵的定义, 这个矩阵的m次就是从某一个点走m步到达另一个点的方案数, 统计下就好了.
#include <cstdio>#include <cstring>#include <cmath>#include <algorithm>#include <iostream>#include <queue>using namespace std;#define maxn 111#define mod 100000int n;long long m;char str[11][11];int tot;void change (char *s) { int len = strlen (s); for (int i = 0; i < len; i++) { if (s[i] == 'A') s[i] = 'a'; else if (s[i] == 'C') s[i] = 'b'; else if (s[i] == 'T') s[i] = 'c'; else s[i] = 'd'; } return ;}struct M { long long a[maxn][maxn]; M () { memset (a, 0, sizeof a); } M operator * (const M &gg) const { M ans; memset (ans.a, 0, sizeof ans.a); for (int i = 0; i < tot; i++) { for (int j = 0; j < tot; j++) { for (int l = 0; l < tot; l++) { ans.a[i][j] += a[i][l]*gg.a[l][j]; ans.a[i][j] %= mod; } } } return ans; } void show () { for (int i = 0; i < tot; i++) { for (int j = 0; j < tot; j++) cout << a[i][j] << " "; cout << endl; } }};M qpow (M a, long long k) { M ans; int i, j; for (i = 0; i < tot; ++i) for (j = 0; j < tot; ++j) ans.a[i][j] = (i == j ? 1 : 0); for(; k; k >>= 1) { if (k&1) ans = ans*a; a = a*a; } return ans;}struct trie { int next[maxn][4], fail[maxn], end[maxn]; int root, cnt; int new_node () { memset (next[cnt], -1, sizeof next[cnt]); end[cnt++] = 0; return cnt-1; } void init () { cnt = 0; root = new_node (); } void insert (char *buf) {//字典树插入一个单词 int len = strlen (buf); int now = root; for (int i = 0; i < len; i++) { int id = buf[i]-'a'; if (next[now][id] == -1) { next[now][id] = new_node (); } now = next[now][id]; } end[now]++; } void build () {//构建fail指针 queue <int> q; fail[root] = root; for (int i = 0; i < 4; i++) { if (next[root][i] == -1) { next[root][i] = root; } else { fail[next[root][i]] = root; q.push (next[root][i]); } } while (!q.empty ()) { int now = q.front (); q.pop (); for (int i = 0; i < 4; i++) { if (next[now][i] == -1) { next[now][i] = next[fail[now]][i]; } else { fail[next[now][i]] = next[fail[now]][i]; q.push (next[now][i]); } } } } int f[maxn];//安全节点对应的节点编号 long long query () { M ans; memset (ans.a, 0, sizeof ans.a); memset (f, -1, sizeof f); tot = 0; for (int i = 0; i < cnt; i++) if (!end[i]) { bool flag = 1; int tmp = i; while (tmp != root) { if (end[tmp]) { flag = 0; break; } tmp = fail[tmp]; } if (flag) { f[i] = tot++; } } for (int i = 0; i < cnt; i++) if (f[i] != -1) {//构造矩阵 int u = f[i]; for (int id = 0; id < 4; id++) { int v = next[i][id]; if (f[v] != -1) { v = f[v]; ans.a[u][v]++; } } } //ans.show (); ans = qpow (ans, m); long long res = 0; for (int i = 0; i < tot; i++) { res += ans.a[0][i]; res %= mod; } return res; }}ac;int main () { while (scanf ("%d%lld", &n, &m) == 2) { ac.init (); for (int i = 1; i <= n; i++) { scanf ("%s", str[i]); change (str[i]); ac.insert (str[i]); } ac.build (); long long ans = ac.query (); printf ("%lld\n", ans); } return 0;}
0 0
- poj 2778 AC自动机+矩阵快速幂
- poj 2778 AC 自动机 + 矩阵快速幂
- POJ 2778 ac自动机+矩阵快速幂
- poj 2778 AC自动机 + 矩阵快速幂
- poj 2778 AC自动机+矩阵快速幂
- poj 2778(ac自动机+矩阵快速幂)
- AC自动机+矩阵快速幂 POJ 2778
- POJ 2778 (AC自动机 矩阵快速幂)
- POJ-2778 ac自动机+矩阵快速幂
- POJ 2778 AC自动机+矩阵快速幂
- POJ 2778:DNA Sequence(AC自动机+矩阵快速幂)
- poj 2778 DNA Sequence 【ac自动机 + dp + 矩阵快速幂】
- poj 2778 AC自动机+DP+矩阵快速幂
- POJ 2778 DNA Sequence【AC自动机+矩阵快速幂】
- poj 2778 (AC自动机+dp+矩阵快速幂)
- poj 2778 DNA Sequence(AC自动机+矩阵快速幂)
- [AC自动机+dp+矩阵快速幂] poj 2778 DNA Sequence
- poj 2778 ac自动机dp矩阵快速幂
- VS如何安装WTL模板
- git新手学习和使用
- VB语言5“用户名”与“密码”实验报告
- 如何使用iClient for JavaScript叠加地图
- ucosIII内核文件分析-os_msg.c
- POJ 2778 (AC自动机 矩阵快速幂)
- 从配置文件读取数据连接信息,利用泛型和java反射机制,写一个公共的增删改查数据库操作类
- iOS利用GCDAsyncSocket发送语音,以及语音wav转码amr
- 观察者模式
- Windows释放端口
- linux重启系统
- UIScrollerView上AutoLayout的总结
- 飞控信号SBUS信号解析为PWM信号输出
- 【每日一课】Python官方文档 5 --- 函数初步