poj--2778DNA Sequence+AC自動機+矩陣快速冪
題目連結:點選進入
如果我們先將所有的病毒字串構建成一棵trie,然後構建一個n長的字串的過程可以看成是從這顆trie樹根節點出發走n步的一個過程,為了不含任何的病毒,則在走的過程中不能經過任何的病毒節點。考慮只走一步的過程,則我們可以得到一個矩陣m[i][j],表示從節點i到節點j有多少種方式。那麼這個矩陣的n次冪就是表示走n步的情況,然後也就可以得到答案了。
問題在於如何獲得這個走一步方案數的矩陣,我們可以利用構造ac自動機的過程,將所有的病毒葉子節點以及以這些節點做字尾的節點標記為病毒節點,然後就可以通過檢查每個節點的所有兒子節點得到到達他們的方案數了。更具體的思路見程式碼
程式碼如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
#define ll long long
struct Matrix
{
ll mat[140][140];
int n;
Matrix(){};
Matrix(int n1)
{
n=n1;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
mat[i][j]=0;
}
Matrix operator *(const Matrix &b) const
{
Matrix ret=Matrix(n);
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
{
for(int k=0;k<n;k++)
ret.mat[i][j]+=mat[i][k]*b.mat[k][j];
ret.mat[i][j]%=100000;
}
return ret;
}
};
Matrix matrixPow(Matrix matrix,int n)
{
Matrix ret = Matrix(matrix.n);
for(int i=0;i<matrix.n;i++)
ret.mat[i][i]=1;
while(n)
{
if(n&1) ret=ret*matrix;
matrix=matrix*matrix;
n=n>>1;
}
return ret;
}
int getIndex(char x)
{
if(x=='A') return 0;
if(x=='T') return 1;
if(x=='C') return 2;
if(x=='G') return 3;
}
struct Trie
{
int next[140][4],fail[140],flag[140];
int root,L;
int newnode()
{
memset(next[L],-1,sizeof(next[L]));
flag[L++]=0;
return L-1;
}
void init()
{
L=0;
root=newnode();
}
void insert(char buf[])
{
int len=strlen(buf);
int now=root;
for(int i=0;i<len;i++)
{
int index=getIndex(buf[i]);
if(next[now][index]==-1)
next[now][index]=newnode();
now=next[now][index];
}
flag[now]++;
}
void build()
{
queue<int>Q;
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(flag[fail[now]])
flag[now]++;
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]);
}
}
}
}
///獲得對應的狀態轉移矩陣
///對trie中的每個節點都檢查其所有兒子節點
void getMatrix(Matrix &matrix)
{
for(int i=0;i<L;i++)
for(int j=0;j<4;j++)
if(!flag[i]&&!flag[next[i][j]])
matrix.mat[i][next[i][j]]++;
}
};
Trie ac;
char str[20];
int main()
{
int m,n;
//freopen("in.txt","r",stdin);
while(scanf("%d%d",&m,&n)!=EOF)
{
Matrix matrix = Matrix(50);
ac.init();
for(int i=0;i<m;i++)
{
scanf("%s",str);
ac.insert(str);
}
ac.build();
ac.getMatrix(matrix);
matrix=matrixPow(matrix,n);
ll ans=0;
//check(matrix);
for(int i=0;i<ac.L;i++)
ans+=matrix.mat[0][i];
printf("%lld\n",ans%100000);
}
return 0;
}
相關文章
- 矩陣快速冪矩陣
- POJ 2778-DNA Sequence(AC自動機+構建鄰接矩陣+矩陣快速冪)矩陣
- 矩陣快速冪(快忘了)矩陣
- 矩陣快速冪總結矩陣
- 【矩陣乘法】【快速冪】遞推矩陣
- 矩陣快速冪加速最短路矩陣
- 演算法學習:矩陣快速冪/矩陣加速演算法矩陣
- HDU 1575 Tr A(矩陣快速冪)矩陣
- HDU 4565 So Easy!(矩陣快速冪)矩陣
- HDU 4686 (推公式+矩陣快速冪)公式矩陣
- POJ 3613 Cow Relays 矩陣乘法Floyd+矩陣快速冪矩陣
- P3390 【模板】矩陣快速冪矩陣
- HDU 4965 Fast Matrix Calculation(矩陣快速冪)AST矩陣
- HDU 2157 How many ways?? (矩陣快速冪)矩陣
- HDU 1005 Number Sequence(矩陣快速冪)矩陣
- HDU 2256Problem of Precision(矩陣快速冪)矩陣
- 從斐波那契到矩陣快速冪矩陣
- HDU 1575 Tr A【矩陣快速冪取模】矩陣
- HDU 1005 Number Sequence:矩陣快速冪矩陣
- HDU5411CRB and Puzzle(矩陣快速冪)矩陣
- HDU3221Brute-force Algorithm(矩陣快速冪&&指數降冪)Go矩陣
- bzoj3240: [Noi2013]矩陣遊戲(矩陣乘法+快速冪)矩陣遊戲
- HDU 2276 - Kiki & Little Kiki 2 (矩陣快速冪)矩陣
- BZOJ 3329 Xorequ:數位dp + 矩陣快速冪矩陣
- HDU 4291 A Short problem(矩陣快速冪+迴圈節)矩陣
- UVA 10655 Contemplation! Algebra (矩陣快速冪)矩陣
- POJ 3150 Cellular Automaton(矩陣快速冪)矩陣
- 費馬小定理 + 費馬大定理 + 勾股數的求解 + 快速冪 + 矩陣快速冪 【模板】矩陣
- 第?課——基於矩陣快速冪的遞推解法矩陣
- bzoj4887: [Tjoi2017]可樂(矩陣乘法+快速冪)矩陣
- LightOJ 1070 Algebraic Problem:矩陣快速冪 + 數學推導AI矩陣
- 【Ac自動機+矩陣加速】poj 2778 DNA Sequence矩陣
- poj 2778 AC自動機與矩陣連乘矩陣
- hdu2243 ac自動機+矩陣連乘矩陣
- HDU 4549 M斐波那契數列(矩陣快速冪+費馬小定理)矩陣
- BZOJ3329: Xorequ(二進位制數位dp 矩陣快速冪)矩陣
- LightOJ 1132 Summing up Powers:矩陣快速冪 + 二項式定理矩陣
- 2015年吉林省賽 Pin Pin Pin(矩陣快速冪)矩陣