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 ...
随机推荐
- 360杀毒导致的 VS 报扩展错误,请查看 ActiveLog.xml
360杀毒将 TypeScript的 tsserver.js 列为木马,结果导致VS2017启动时,总是报错,将其加为信任即可解决.
- vue-vuex安装
npm install vuex --save 然后在package.json文件的 dependencies中就看到有了一个vuex的文件 解释一下 dependencies生产环境它的意思就是上线 ...
- Flexigrid默认是可以选择多行
1.Flexigrid默认是可以选择多行,那么如何设置其只能选一行呢?今天看了看Flexigrid的源码,发现有个属性可以控制: $(this).click(function (e) { var ob ...
- vue-music 关于Search(搜索页面)-- 搜索结果优化
搜索结果 列表点击跳转到相应的歌手详情页或者 歌曲页面,通过子路由跳转,和singer 组件一样 在suggest.vue 组件判断如果点击的是歌手,则new 一个歌手对象,通过这个对象的id 属性值 ...
- 可持久化01Trie树【p4735(bzoj3261)】最大异或和
Description 给定一个非负整数序列\(\{a\}\),初始长度为\(N\). 有\(M\)个操作,有以下两种操作类型: A x:添加操作,表示在序列末尾添加一个数\(x\),序列的长度\(N ...
- Nginx日志统一格式
统一格式如下:nginx.conf 纯文本: log_format main '$remote_addr - $remote_user [$time_local] "$request&quo ...
- 35、Flask实战第35天:权限设计
二进制及其相关运算 认识二进制 0,1,2,3,4,5,6,7,8,9,10:逢10进1 0,1:逢2进1 二进制转十进制 十进制 二进制 0 0 1 1 2 10 3 11 4 100 255 11 ...
- 封装boto3 api用于服务器端与AWS S3交互
由于使用AWS的时候,需要S3来存储重要的数据. 使用Python的boto3时候,很多重要的参数设置有点繁琐. 重新写了一个类来封装操作S3的api.分享一下: https://github.com ...
- [BZOJ 1724] Fence Repair
这大概是BZOJ里除了A+B Problem最水的一道题了吧 题面:http://www.lydsy.com/JudgeOnline/problem.php?id=1724 这道题其实有一些思路还是可 ...
- Problem F: 调用函数,判断各位数字立方和是否等于它本身
#include<stdio.h> #include<math.h> int is(int number)//定义函数 { ; ) { s=number%; sum=sum+p ...