poj 2778 AC自己主动机 + 矩阵高速幂
// poj 2778 AC自己主动机 + 矩阵高速幂
//
// 题目链接:
//
// http://poj.org/problem?id=2778
//
// 解题思路:
//
// 建立AC自己主动机,确定状态之间的关系,构造出,走一步
// 能到达的状态矩阵,然后进行n次乘法,就能够得到状态间
// 走n步的方法数.
// 精髓:
// 1):这个ac自己主动机有一些特别,根节点是为空串,然而
// 每走一步的时候,假设没法走了,这时候,不一定是回到根
// 节点,由于有可能单个的字符时病毒,这样,不是随便就能达到
// 所谓的根节点的,所以每次初始化的时候,不能是0,而应该是
// -1.
//
// 感悟:
//
// 这道AC自己主动机,開始我是全然不会,知道是AC自己主动机+矩阵高速幂
// 開始,自以为AC自己主动机构造的非常对,并且例子都过了好嘛,结果一直是
// wrong answer.我就不信邪了,肯定是博主博客有错误,我就将博主的
// 交了一发,然而,博主的过了,我的没过.哎,一阵伤心,但心里也是再次
// 燃起了希望之火,还是能够搞得.然而我就细致研究,对拍呗,自己造了
// 几个例子.发现以下这组:
// 4 2
// A
// C
// T
// GT
// 这组例子,答案应该是1,而我的答案是3.我仿佛一下子恍然大悟,发现
// 单个字符是病毒,不能走回根节点.明确了过后,一改,就AC了,尽管速度
// 有点慢,可是我发现自己对AC自己主动机的理解又有了一点小小的新的拓展
// 尽管作为菜鸟的我敢于怀疑是一件好事,可是自己的不正确就是不正确,不要
// 由于自己的自信就去刻意寻找别人的错误,觉得别人是错误的.有着一颗
// 敢于承认错误,并且接受正确观念,并明悟的人,我觉得光明,就在前方! #include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std; typedef long long ll; const int MAX_NODE = 110;
const ll MOD = 100000;
const int MAX_N = 110; struct Matrix{
ll mat[MAX_N][MAX_N];
}res; int n,m; struct Aho_Corasick{ int ch[MAX_NODE][4]; bool val[MAX_NODE]; int f[MAX_NODE]; //int last[MAX_NODE]; int sz; void init(){
memset(ch[0],-1,sizeof(ch[0]));
val[0] = 0;
sz = 1;
f[0] = 0;
//last[0] = 0;
} int idx(char c){
if (c == 'A')
return 0;
if (c == 'T')
return 1;
if (c == 'C')
return 2;
return 3;
} void insert(char *s){
int u = 0;
int n = strlen(s);
for (int i=0;i<n;i++){
int c = idx(s[i]);
if (ch[u][c]==-1){
memset(ch[sz],-1,sizeof(ch[sz]));
val[sz] = 0;
ch[u][c] = sz++;
}
u = ch[u][c];
}
val[u] = true;
} void getfail(){
queue<int> que;
f[0] = 0;
for (int c = 0;c < 4;c++){
int u = ch[0][c];
if (u!=-1){
que.push(u);
f[u] = 0;
// last[u] = 0;
}else{
ch[0][c] = 0; //表示当此c单个字符不是病毒的时候,则能够走回根
}
} while(!que.empty()){
int r = que.front();
que.pop(); if (val[f[r]]) // 当r的某个后缀为病毒的时候标记此r
val[r] = true; for (int c = 0; c < 4;c++){
int u = ch[r][c]; if (u == -1){
ch[r][c] = ch[f[r]][c]; //把不存在的边接上去
continue;
}
que.push(u); int v = f[r];
while(v && ch[v][c]==-1)
v = f[v]; f[u] = ch[v][c]; //last[u] = val[f[u]] ? f[u] : last[f[u]];
}
}
} void get_matrix(){ memset(res.mat,0,sizeof(res.mat)); for (int u=0;u<sz;u++){
for (int c = 0;c < 4;c++){
if (!val[u] && !val[ch[u][c]])
res.mat[u][ch[u][c]]++;
}
}
} }ac; Matrix Mulity(Matrix a,Matrix b){
Matrix ans; for (int i=0;i < ac.sz;i++)
for (int j=0;j < ac.sz;j++){
ans.mat[i][j] = 0;
for (int k=0;k < ac.sz ;k++)
ans.mat[i][j] = (ans.mat[i][j] + a.mat[i][k] * b.mat[k][j])%MOD;
ans.mat[i][j] %= MOD;
} return ans;
} Matrix Matrix_power(Matrix a,int b){
Matrix ans;
memset(ans.mat,0,sizeof(ans.mat));
for (int i=0;i<ac.sz;i++)
ans.mat[i][i] = 1; while(b){
if (b & 1) ans = Mulity(ans,a);
a = Mulity(a,a);
b >>=1;
}
return ans;
} void print(Matrix r){
for (int i=0;i<ac.sz;i++){
for (int j=0;j<ac.sz;j++)
cout << r.mat[i][j] << " ";
cout << endl;
}
} void input(){
ac.init();
char s[20];
for (int i=1;i<=m;i++){
scanf("%s",s);
ac.insert(s);
}
ac.getfail();
ac.get_matrix();
// print(res);
res = Matrix_power(res,n);
// cout << endl;
// print(res);
ll ans = 0; for (int i=0;i<ac.sz;i++){
ans = (ans + res.mat[0][i])%MOD;
}
cout << ans%MOD << endl;
} int main(){
//freopen("1.txt","r",stdin);
while(scanf("%d%d",&m,&n)!=EOF){
// puts("-------");
input();
}
return 0;
}
poj 2778 AC自己主动机 + 矩阵高速幂的更多相关文章
- POJ 2778 AC自己主动机+矩阵幂 不错的题
http://poj.org/problem?id=2778 有空再又一次做下,对状态图的理解非常重要 题解: http://blog.csdn.net/morgan_xww/article/deta ...
- hdu 2243 考研绝望——复杂的文字(AC自己主动机+矩阵高速功率)
pid=2243" target="_blank" style="">题目链接:hdu 2243 考研路茫茫--单词情结 题目大意:略. 解题思 ...
- Hdu 2243 考研路茫茫——单词情结 (AC自己主动机+矩阵)
哎哟喂.中文题. . .不说题意了. 首先做过POJ 2778能够知道AC自己主动机是能够求出长度为L的串中不含病毒串的数量的. POJ 2778的大概思路就是先用全部给的病毒串建一个AC自己主动机. ...
- POJ 3613 Cow Relays (floyd + 矩阵高速幂)
题目大意: 求刚好经过K条路的最短路 我们知道假设一个矩阵A[i][j] 表示表示 i-j 是否可达 那么 A*A=B B[i][j] 就表示 i-j 刚好走过两条路的方法数 那么同理 我们把 ...
- Hdu 3962 Microgene (AC自己主动机+矩阵)
标题效果: 构造一个字符串,使得有两个和两个以上的目标串.长短L这一系列有多少串都. IDEAS: 只有全款减有1一些字符串,没有目标就是答案. 假定数据是非常小的,够用dp解.dp[i][j][k] ...
- POJ 2778 DNA Sequence (AC自己主动机 + dp)
DNA Sequence 题意:DNA的序列由ACTG四个字母组成,如今给定m个不可行的序列.问随机构成的长度为n的序列中.有多少种序列是可行的(仅仅要包括一个不可行序列便不可行).个数非常大.对10 ...
- POJ 1625 Censored! (AC自己主动机 + 高精度 + DP)
题目链接:Censored! 解析:AC自己主动机 + 高精度 + 简单DP. 字符有可能会超过128.用map映射一下就可以. 中间的数太大.得上高精度. 用矩阵高速幂会超时,简单的DP就能解决时间 ...
- POJ 3691 & HDU 2457 DNA repair (AC自己主动机,DP)
http://poj.org/problem?id=3691 http://acm.hdu.edu.cn/showproblem.php?pid=2457 DNA repair Time Limit: ...
- poj 1699 Best Sequence(AC自己主动机+如压力DP)
id=1699" target="_blank" style="">题目链接:poj 1699 Best Sequence 题目大意:给定N个D ...
随机推荐
- [jquery] input值发生变化则触发
$("#a").val("你好").trigger("change"); $("#a").bind("chan ...
- Codeforces 1131 F. Asya And Kittens-双向链表(模拟或者STL list)+并查集(或者STL list的splice()函数)-对不起,我太菜了。。。 (Codeforces Round #541 (Div. 2))
F. Asya And Kittens time limit per test 2 seconds memory limit per test 256 megabytes input standard ...
- 转:Filter的执行顺序与实例
转:http://www.cnblogs.com/Fskjb/archive/2010/03/27/1698448.html Filter的执行顺序与实例 Filter介绍 Filter可认为是Ser ...
- Django常用内置过滤器
1.add 此过滤器将首先尝试将两个值强制为整数.如果失败,它会尝试将值一起添加.这将工作在一些数据类型(字符串,列表等)和失败在其他人.如果失败,结果将是一个空字符串. {{ value | add ...
- ExtJs基础
方法和属性 Ext.caeate方法相当于创建一个实例对象 renderTo:Ext.getBody() 新创建的组件渲染到什么位置 grid.render('grid-example'); /re ...
- 洛谷——P3905 道路重建
P3905 道路重建 题目描述 从前,在一个王国中,在n个城市间有m条道路连接,而且任意两个城市之间至多有一条道路直接相连.在经过一次严重的战争之后,有d条道路被破坏了.国王想要修复国家的道路系统,现 ...
- 10 个常用的 es6 特性
1. const and let 除了函数作用域之外,增加了块级作用域和常量.const 定义的绑定不可以修改,let定义的绑定在{ }不能访问.之前的 var 如果不在函数作用域内,相当于定义了一 ...
- ABP+NetCore+Vue.js实现增删改查
ABP我就不多介绍了,不知道的可以自己百度 本篇开发工具VS2017,数据库SQL SERVER2012,系统Win7 1.去ABP官网下载对应的模板,下载地址:https://aspnetboile ...
- Linux基础系列-Day5
网络管理 ifconfig网络管理工具 ifconfig依赖于命令中使用一些选项属性,不仅可以被用来简单地获取网络接口配置信息,还可以修改这些配置,但是通过ifconfig修改的通常为临时配置,即系统 ...
- (疯狂java)第二课
(本文章只是为了好玩,没有别的意思,有理解错误之处,恳请提醒,谢谢) 三.数据类型和运算符 想了一下今天看的内容好像依然大脑停留在用C语言去理解java,感觉有点奇怪,为啥本章叫数据类型和运算符,上来 ...