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 ...
随机推荐
- 前端读者 | 前端构建工具Gulp
@羯瑞 整理 前言 前端工具现在层出不穷,网上搜下一大片,就看你怎么去使用了,基于项目看用什么样的构建工具.有的工具提供的功能还是非常强大的. FIS.百度团队的产品.现在百度的多个产品中使用.面向前 ...
- 关于自建yum源拾遗
yum参数解释[updates]--->源name=CentOS-$releasever - Updates --->源的名字baseurl=http://mirror.centos.or ...
- 阿里云Maven仓库配置,Maven镜像配置
Jenkins通过maven对java代码打包编译时,速度太慢,所以修改为阿里的Maven仓库 修改如下: [root@7mini-node2 conf]# vim /software/apache- ...
- OpenStack 认证服务 KeyStone部署 (四)
Keystone作用: 用户与认证:用户权限与用户行为跟踪: 服务目录:提供一个服务目录,包括所有服务项和相关Api的断点 SOA相关知识 Keystone主要两大功能用户认证和服务目录(相当于一个注 ...
- zoj 4020 The 18th Zhejiang University Programming Contest Sponsored by TuSimple - G Traffic Light(广搜)
题目链接:The 18th Zhejiang University Programming Contest Sponsored by TuSimple - G Traffic Light 题解: 题意 ...
- ESLint 使用入门
在团队协作中,为避免低级 Bug.产出风格统一的代码,会预先制定编码规范.使用 Lint 工具和代码风格检测工具,则可以辅助编码规范执行,有效控制代码质量. 在以前的项目中,我们选择 JSHint 和 ...
- Codeforces 1 C. Ancient Berland Circus-几何数学题+浮点数求gcd ( Codeforces Beta Round #1)
C. Ancient Berland Circus time limit per test 2 seconds memory limit per test 64 megabytes input sta ...
- flutter vscode插件
代码片段
- EL使用技巧
☞控制页面元素显示与否 实现效果: 实现方案: ...... <div style="display:${empty param.hideTitle ? 'auto' : 'none' ...
- python基础之序列化 time random os
序列化与反序列化 json pickle 1.什么是序列化与反序列化? 序列化就是将内存中的数据结构转成一种中间格式储存到硬盘或者基于网络传输 反序列化是网络,硬盘将被序列化的对象重新读到内存 2. ...