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 ...
随机推荐
- T-SQL备忘(6):常用内置函数
日期和时间函数: 1.获取当前时间:GETDATE() select GETDATE() 返回: 2015-04-27 20:52:06.700 2.返回时间的部分(日.月.年) a.获取日: sel ...
- mac 远程桌面连接分享
mac 远程桌面连接分享 8.0版本 https://pan.baidu.com/s/1wgVvAmQreGwYZAhLST764w 10.0版本 https://pan.baidu.com/s/1Y ...
- 利用jquery.touchSwipe.js实现的移动滑屏效果。
利用jquery.touchSwipe.js实现的移动滑屏效果. 亲测:兼容ie8及各种浏览器 <script type="text/javascript" src=&quo ...
- Jenkins发布PHP代码
实验环境 10.0.0.12 Jenkins服务器 10.0.0.13 远程服务器 一个远程的公开的git仓库(php代码在这个仓库里) 一.检查插件是否安装并安装插件 在通过Jenkins发布php ...
- 解决nginx+php二级页面显示空白的问题
迁移官网商城的发现主页的二级界面显示空白页,此https商城网站 后修改nginx配置,显示正常 添加 location ~ [^/]\.php(/|$) { #fastcgi_pass remote ...
- php漏洞tips
1.php后缀限制 'php,php3,php4,php5,php6,php7,phpsh,inc,phtml','PHT'; 2.php木马 <?php echo shell_exec($_G ...
- ARM芯片stm32中的AHB和APB
AHB,是Advanced High performance Bus的缩写,译作高级高性能总线,这是一种“系统总线”.AHB主要用于高性能模块(如CPU.DMA和DSP等)之间的连接.AHB 系统由主 ...
- python的reduce()函数(转)
reduce()函数也是Python内置的一个高阶函数. reduce()函数接收的参数和 map()类似,一个函数 f,一个list,但行为和 map()不同,reduce()传入的函数 f 必须接 ...
- 【BZOJ 1901】【ZJU 2112】Dynamic Rankings
http://www.lydsy.com/JudgeOnline/problem.php?id=1901 重新用整体二分写了一下. 整体二分的思想详见论文. 貌似带修区间k大和静态区间k大都是\(O( ...
- [BZOJ2226][SPOJ5971]LCMSum(莫比乌斯反演)
2226: [Spoj 5971] LCMSum Time Limit: 20 Sec Memory Limit: 259 MBSubmit: 1949 Solved: 852[Submit][S ...