//	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自己主动机 + 矩阵高速幂的更多相关文章

  1. POJ 2778 AC自己主动机+矩阵幂 不错的题

    http://poj.org/problem?id=2778 有空再又一次做下,对状态图的理解非常重要 题解: http://blog.csdn.net/morgan_xww/article/deta ...

  2. hdu 2243 考研绝望——复杂的文字(AC自己主动机+矩阵高速功率)

    pid=2243" target="_blank" style="">题目链接:hdu 2243 考研路茫茫--单词情结 题目大意:略. 解题思 ...

  3. Hdu 2243 考研路茫茫——单词情结 (AC自己主动机+矩阵)

    哎哟喂.中文题. . .不说题意了. 首先做过POJ 2778能够知道AC自己主动机是能够求出长度为L的串中不含病毒串的数量的. POJ 2778的大概思路就是先用全部给的病毒串建一个AC自己主动机. ...

  4. POJ 3613 Cow Relays (floyd + 矩阵高速幂)

    题目大意: 求刚好经过K条路的最短路 我们知道假设一个矩阵A[i][j] 表示表示 i-j 是否可达 那么 A*A=B  B[i][j]  就表示   i-j 刚好走过两条路的方法数 那么同理 我们把 ...

  5. Hdu 3962 Microgene (AC自己主动机+矩阵)

    标题效果: 构造一个字符串,使得有两个和两个以上的目标串.长短L这一系列有多少串都. IDEAS: 只有全款减有1一些字符串,没有目标就是答案. 假定数据是非常小的,够用dp解.dp[i][j][k] ...

  6. POJ 2778 DNA Sequence (AC自己主动机 + dp)

    DNA Sequence 题意:DNA的序列由ACTG四个字母组成,如今给定m个不可行的序列.问随机构成的长度为n的序列中.有多少种序列是可行的(仅仅要包括一个不可行序列便不可行).个数非常大.对10 ...

  7. POJ 1625 Censored! (AC自己主动机 + 高精度 + DP)

    题目链接:Censored! 解析:AC自己主动机 + 高精度 + 简单DP. 字符有可能会超过128.用map映射一下就可以. 中间的数太大.得上高精度. 用矩阵高速幂会超时,简单的DP就能解决时间 ...

  8. POJ 3691 &amp; 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: ...

  9. poj 1699 Best Sequence(AC自己主动机+如压力DP)

    id=1699" target="_blank" style="">题目链接:poj 1699 Best Sequence 题目大意:给定N个D ...

随机推荐

  1. Homebrew安装gradle及配置myeclipse

    brew install gradle 对,你没看错.就只有一行命令搞定. 然后验证安装 nicknailodeMacBook-Pro:~ nicknailo$ gradle -v --------- ...

  2. 转:fortios 5.4后门植入

    提示: 1.经过实验,fortios 5.4 beta4也是可以的. 2.在实验时,选择先下载fortios 5.2(做了快照),再升级5.4,则虚拟机挂载需要选择FortiGate-VM-disk1 ...

  3. 设计模式-命令模式(Command Pattern)

    本文由@呆代待殆原创,转载请注明出处:http://www.cnblogs.com/coffeeSS/ 命令模式简述 命令模式的主要作用是将“行为请求者”和“行为实现者”解耦.举个例子,假如我们现在要 ...

  4. uva 10910(子集和问题)

    Marks Distribution Time limit: 3.000 seconds In an examination one student appeared in N subjects an ...

  5. rmq问题:ST表

    存板子.O(nlogn)预处理,O(1)查询.空间O(nlogn). int d[1000006][25]; int mn[1000006]; void rmq_init() { for(int i= ...

  6. 【深度优先搜索】mr353-取奶

    应该是USACO的题目,暂时没有找到对应出处. [题目大意] 农夫约翰要量取 Q(1 <= Q <= 20,000)夸脱(夸脱,quarts,容积单位——译者注) 他的最好的牛奶,并把它装 ...

  7. 小Z的城市之旅

    题目大意: 从(0,0)走到(x,y),每次可以向上下左右走一格,问走r步刚好到(x,y)的方案数. 思路: 找规律发现答案就是C((r+x-y)/2,r)*C((r-x-y)/2,r). #incl ...

  8. Problem H: 零起点学算法109——单数变复数

    #include <stdio.h> #include<string.h> int main(void) { int n; ]; scanf("%d",&a ...

  9. Codeforces Round #127 (Div. 1) C. Fragile Bridges dp

    C. Fragile Bridges 题目连接: http://codeforces.com/contest/201/problem/C Description You are playing a v ...

  10. php中文件上传需要注意的几点

    1.首先要开启php.ini中的文件上传,打开php.ini 配置文件,查找 File Uploads ,在这个区域有以下3个选项: ;;;;;;;;;;;;;;;; ; File Uploads ; ...