poj 2778 DNA Sequence(ac自动机+矩阵快速幂)
Posted Gealo
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了poj 2778 DNA Sequence(ac自动机+矩阵快速幂)相关的知识,希望对你有一定的参考价值。
题目链接:http://poj.org/problem?id=2778
题解:像这种能够找到长度为m的不包含子串的串有几种可以考虑用邻接矩阵,就是考虑从每一点出发走一次能够到达的位置,那么走两次能到达的位置就是矩阵的2次幂以此类推。于是可以利用自动机来得到矩阵然后就是矩阵快速幂。
#include <iostream> #include <cstring> #include <cstdio> #include <queue> #include <map> #define mod 100000 using namespace std; typedef long long ll; const int M = 5e5 + 50; struct Matrix { ll dp[123][123]; }; Matrix Mul(Matrix a , Matrix b , int Max) { Matrix c; int i , j , k ; memset(c.dp , 0 , sizeof(c.dp)); for(i = 0 ; i <= Max ; i++) { for(j = 0 ; j <= Max ; j++) { for(k = 0 ; k <= Max ; k++) c.dp[i][j] = (a.dp[i][k] * b.dp[k][j] + c.dp[i][j]) % mod; } } return c ; } Matrix Matrix_quick_pow(Matrix a , int k , int Max) { Matrix res; memset(res.dp , 0 , sizeof(res.dp)); for(int i = 0 ; i <= Max ; i++) res.dp[i][i] = 1; while(k) { if(k & 1) res = Mul(res , a , Max); k >>= 1; a = Mul(a , a , Max); } return res; } bool End[M]; int Next[M][4] , fail[M] , root , L , cnt; int newnode() { for(int i = 0 ; i < 4 ; i++) { Next[L][i] = -1; } End[L++] = false; return L - 1; } void init() { L = 0; root = newnode(); } void build(char s[]) { int len = strlen(s); int now = root; for(int i = 0 ; i < len ; i++) { int id = 0; if(s[i] == ‘A‘) id = 0; if(s[i] == ‘C‘) id = 1; if(s[i] == ‘G‘) id = 2; if(s[i] == ‘T‘) id = 3; if(Next[now][id] == -1) { Next[now][id] = newnode(); } now = Next[now][id]; } End[now] = true; } bool vis[123]; queue<int>q; void get_fail() { while(!q.empty()) q.pop(); fail[root]=root; for(int i = 0 ; i < 4 ; i++) { if(Next[root][i] == -1) Next[root][i] = root; else { fail[Next[root][i]] = root; q.push(Next[root][i]); } } while(!q.empty()) { int now = q.front(); q.pop(); if(End[fail[now]]) End[now] = true; for(int i = 0 ; i < 4 ; i++) { if(Next[now][i] == -1) Next[now][i] = Next[fail[now]][i]; else { fail[Next[now][i]] = Next[fail[now]][i]; q.push(Next[now][i]); } } } } Matrix a; Matrix getfair() { memset(a.dp , 0 , sizeof(a.dp)); memset(vis , false , sizeof(vis)); while(!q.empty()) q.pop(); q.push(root); vis[root] = true; while(!q.empty()) { int now = q.front(); q.pop(); for(int i = 0 ; i < 4 ; i++) { if(!End[now] && !End[Next[now][i]]) a.dp[now][Next[now][i]]++; if(!vis[Next[now][i]]) vis[Next[now][i]] = true , q.push(Next[now][i]); } } return a; } char s[20]; int main() { int n , m; while(~scanf("%d%d" , &n , &m)) { init(); while(n--) { scanf("%s" , s); build(s); } get_fail(); a = getfair(); a = Matrix_quick_pow(a , m , L); ll ans = 0; for(int i = 0 ; i < L ; i++) { ans += a.dp[0][i]; ans %= mod; } printf("%lld\n" , ans); } return 0; }
以上是关于poj 2778 DNA Sequence(ac自动机+矩阵快速幂)的主要内容,如果未能解决你的问题,请参考以下文章
POJ 2778 DNA Sequence(AC自动机+矩阵)
poj2778 DNA Sequence(AC自动机+矩阵快速幂)
poj2778 DNA Sequence(AC自动机+矩阵快速幂)