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 mean that the animal may have a genetic disease. Until now scientists have found several those segments, the problem is how many kinds of DNA sequences of a species don’t contain those segments.
Suppose that DNA sequences of a species is a sequence that consist of A, C, T and G,and the length of sequences is a given integer n.
Input
First line contains two integer m (0 <= m <= 10), n (1 <= n <=2000000000). Here, m is the number of genetic disease segment, and n is the length of sequences.
Next m lines each line contain a DNA genetic disease segment, and length of these segments is not larger than 10.
Output
An integer, the number of DNA sequences, mod 100000.
Sample Input
4 3
AT
AC
AG
AA
Sample Output
36
题目大意:给出n个病毒串,问长度为m的DNA序列中有多少种是不包含病毒串的。
解题思路:我们将病毒串加入AC自动机中,然后我们先创建一个矩阵表示从i点走到j点的长度为1的字符串中不包含病毒串的种类数。我们知道,如果从i点到j点的长度为2的字符串可以由从i点到k点长度为1的字符串和从k点到j点长度为1的字符串拼接得到,所以其实我们列出来所有的k就可以看出这是一个矩阵乘法公式。所以我们将这个矩阵乘以m次就可以啦。然后计算从0点到其他点的种类数。
代码:
#pragma GCC optimize(2)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <stack>
#include <bitset>
#include <queue>
//#include <random>
#include <time.h>
using namespace std;
#define int long long
#define ull unsigned long long
#define ls root<<1
#define rs root<<1|1
const int inf=1ll*1<<60;
const int maxn=1e4+10;
const int maxm=1e6+10;
const int mod=100000;
char arr[110];
int trie[110][4],fail[110],tot,val[110],idx[128];
void add(char *s)
{
int now=0;
for(int i=0;s[i]!='\0';i++){
int x=idx[s[i]];
if(!trie[now][x]) trie[now][x]=++tot;
now=trie[now][x];
}
val[now]=1;
}
void getfail()
{
queue<int> q;
for(int i=0;i<4;i++)
if(trie[0][i])q.push(trie[0][i]);
while(!q.empty()){
int now=q.front();q.pop();
for(int i=0;i<4;i++){
if(trie[now][i]){
fail[trie[now][i]]=trie[fail[now]][i];
q.push(trie[now][i]);
}
else trie[now][i]=trie[fail[now]][i];
val[trie[now][i]]|=val[trie[fail[now]][i]];
}
}
}
struct martix
{
int mat[110][110];
martix(){
memset(mat,0,sizeof mat);
}
};
martix operator *(const martix a,const martix b)
{
martix z;
for(int i=0;i<=tot;i++){
for(int j=0;j<=tot;j++){
for(int k=0;k<=tot;k++){
z.mat[i][j]+=a.mat[i][k]*b.mat[k][j];
z.mat[i][j]%=mod;
}
}
}
return z;
}
signed main()
{
int n,m;
scanf("%lld%lld",&n,&m);
idx['A']=0,idx['C']=1,idx['G']=2,idx['T']=3;
for(int i=0;i<n;i++){
scanf("%s",arr);
add(arr);
}
getfail();
martix e,x;
for(int i=0;i<=tot;i++){
e.mat[i][i]=1;
}
for(int i=0;i<=tot;i++){
if(val[i])continue;
for(int j=0;j<4;j++){
if(val[trie[i][j]])continue;
x.mat[i][trie[i][j]]++;
}
}
while(m){
if(m&1)e=e*x;
x=x*x;
m>>=1;
}
int ans=0;
for(int i=0;i<=tot;i++){
ans+=e.mat[0][i];
ans%=mod;
}
printf("%lld\n",ans);
}