DNA Sequence POJ - 2778 AC 自动机 矩阵乘法

定义重载运算的时候一定要将矩阵初始化,因为这个调了一上午......

Code:

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#include<string>
#define maxn 100000
typedef long long ll;
using namespace std;
void setIO(string a){ freopen((a+".in").c_str(),"r",stdin); }

char arr[maxn];
int mod, nodes;
struct matrix{
    int m[105][105];
}mat;
void init(matrix &c){ for(int i=0;i<=nodes;++i) c.m[i][i]=1; }
void get(matrix &c) {for(int i=0;i<=nodes;++i) for(int j=0;j<=nodes;++j) c.m[i][j]=0;}
void print(matrix a){
	for(int i=0;i<=nodes;++i){
		for(int j=0;j<=nodes;++j) printf("%d ",a.m[i][j]);
		printf("\n");
	}
}
matrix operator*(matrix a,matrix b){
	matrix c;
	get(c);
	for(int i=0;i<=nodes;++i)
		for(int j=0;j<=nodes;++j)
			for(int k=0;k<=nodes;++k){
				c.m[i][j]+=((ll)a.m[i][k]*b.m[k][j])%mod;
				c.m[i][j]%=mod;
			}
	return c;
}
matrix power(matrix a,long long k){
    matrix ans;
    for(int i=0;i<=nodes;++i) ans.m[i][i]=1;
    while(k){
        if(k&1)ans=ans*a;
        a=a*a;
        k/=2;
    }
    return ans;
}
struct Automaton{
	#define sigma 4
	int get(char s){
		if(s==‘A‘) return 0;
		if(s==‘C‘) return 1;
		if(s==‘T‘) return 2;
		if(s==‘G‘) return 3;
	}
	int ch[maxn][sigma],tag[maxn],fail[maxn];
	void insert(char str[]){
		int n=strlen(str);
		int j=0;
		for(int i=0;i<n;++i){
			if(!ch[j][get(str[i])]) ch[j][get(str[i])]=++nodes;
			j=ch[j][get(str[i])];
		}
		tag[j]=1;
	}
	queue<int>Q;
	void build(){
		for(int i=0;i<sigma;++i) if(ch[0][i]) Q.push(ch[0][i]);
		while(!Q.empty()){
			int u=Q.front();Q.pop();
			if(tag[fail[u]]) tag[u]=1;
			for(int i=0;i<sigma;++i){
				int r=ch[u][i];
				if(!r) { ch[u][i]=ch[fail[u]][i]; continue; }
				fail[r]=ch[fail[u]][i];
				Q.push(r);
			}
		}

		for(int i=0;i<=nodes;++i)
		    for(int j=0;j<sigma;++j)
		    	if(!tag[i]&&!tag[ch[i][j]]) mat.m[i][ch[i][j]]+=1;

	}
}aho;

int main(){
	//setIO("input");
	mod=100000;
	int m, ans=0;  long long n;
	scanf("%d%lld",&m,&n);
	for(int i=1;i<=m;++i)scanf("%s",arr), aho.insert(arr);
	aho.build();
    matrix fin=power(mat,n);
    for(int i=0;i<=nodes;++i)  ans=(ans+fin.m[0][i])%mod;
    printf("%d",ans);
    return 0;
}

  

原文地址:https://www.cnblogs.com/guangheli/p/9903163.html

时间: 2024-10-06 00:29:18

DNA Sequence POJ - 2778 AC 自动机 矩阵乘法的相关文章

poj 2778 AC自动机 + 矩阵快速幂

// poj 2778 AC自动机 + 矩阵快速幂 // // 题目链接: // // http://poj.org/problem?id=2778 // // 解题思路: // // 建立AC自动机,确定状态之间的关系,构造出,走一步 // 能到达的状态矩阵,然后进行n次乘法,就可以得到状态间 // 走n步的方法数. // 精髓: // 1):这个ac自动机有一些特别,根节点是为空串,然而 // 每走一步的时候,如果没法走了,这时候,不一定是回到根 // 节点,因为有可能单个的字符时病毒,这样

POJ 2778 AC自动机+矩阵幂 不错的题

http://poj.org/problem?id=2778 有空再重新做下,对状态图的理解很重要 题解: http://blog.csdn.net/morgan_xww/article/details/7834801 另外做了矩阵幂的模板: //ac.sz是矩阵的大小 void mulmtr(long long x[MAXNODE][MAXNODE],long long y[MAXNODE][MAXNODE])//y=x*y { ll tmp[MAXNODE][MAXNODE]; for(in

poj 2778 AC自动机与矩阵连乘

http://poj.org/problem?id=2778 Description It's well known that DNA Sequence is a sequence only contains A, C, T and G, and it's very useful to analyze a segment of DNA Sequence,For example, if a animal's DNA sequence contains segment ATC then it may

poj2778DNA Sequence(AC自动机+矩阵乘法)

链接 看此题前先看一下matrix67大神写的关于十个矩阵的题目中的一个,如下: 经典题目8 给定一个有向图,问从A点恰好走k步(允许重复经过边)到达B点的方案数mod p的值    把给定的图转为邻接矩阵,即A(i,j)=1当且仅当存在一条边i->j.令C=A*A,那么C(i,j)=ΣA(i,k)*A(k,j),实际上就等于从点i到点j恰好经过2条边的路径数(枚举k为中转点).类似地,C*A的第i行第j列就表示从i到j经过3条边的路径数.同理,如果要求经过k步的路径数,我们只需要二分求出A^k

BZOJ 1009 [HNOI2008]GT考试 AC自动机+矩阵乘法

题意:链接略 方法: AC自动机+矩阵乘法 解析: 和POJ 2778 一样的题. 大概的思路就是我们建AC自动机的时候需要注意如果某个点是一个串的结尾的话,那么下面的节点都要看成结尾节点. 然后按照AC自动机赋一下矩阵内部值就好了. 赋的矩阵代表从一个节点走一步走到另一个节点有多少方案. 然后经典模型,矩阵的n次方即可. 代码: #include <queue> #include <cstdio> #include <cstring> #include <ios

POJ 2778 DNA Sequence (AC自动机,矩阵乘法)

题意:给定n个不能出现的模式串,给定一个长度m,要求长度为m的合法串有多少种. 思路:用AC自动机,利用AC自动机上的节点做矩阵乘法. 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #include<string> 6 #include<algorithm> 7 #include<queue> 8 #defin

DNA Sequence(POJ2778 AC自动机dp+矩阵加速)

传送门 DNA Sequence Time Limit: 1000MS   Memory Limit: 65536K       Description It's well known that DNA Sequence is a sequence only contains A, C, T and G, and it's very useful to analyze a segment of DNA Sequence,For example, if a animal's DNA sequenc

[BZOJ 1009] [HNOI2008] GT考试 【AC自动机 + 矩阵乘法优化DP】

题目链接:BZOJ - 1009 题目分析 题目要求求出不包含给定字符串的长度为 n 的字符串的数量. 既然这样,应该就是 KMP + DP ,用 f[i][j] 表示长度为 i ,匹配到模式串第 j 位的字符串个数,然后转移就是可以从第 j 位加上一个字符转移到另一个位置. 然而..我并没有写过KMP + DP,我觉得还是写AC自动机+DP比较简单..于是,尽管只有一个模式串,我还是写了AC自动机+DP. 然后就是建出AC自动机,f[i][j] 表示长度为 i ,走到节点 j 的字符串的个数.

BZOJ 2553 BeiJing2011 禁忌 AC自动机+矩阵乘法

题目大意:给定n个模式串,定义一个字符串的伤害为所有子串的划分中最多包含的模式串数量,求长度为len的字符串的伤害期望值 小五prpr,恋恋prpr,大小姐prpr 首先建立AC自动机 令f[i][j]表示长度为i的字符串在AC自动机上的第j个节点的伤害期望值 如果要走到某个节点是危险节点或者fail指针指向危险节点,就ans++,然后回到根节点 这样构造出来的矩阵做快速幂= = 这么做都会把- - 不会别骂我- - 但是跑完发现找不到答案- - 因此我们需要稍微改造一下- - 新建一个节点 如