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.
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.
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
Source
题意:给你一堆DNA子串,让你求长度为n且不包含这些子串的DNA序列有多少个。
分析:AC自动机构造的同时构造转移矩阵,然后上矩阵快速幂。
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#define MAXNODE 105
using namespace std;
int m,n;
char s[15];
struct Acautomata
{
int ch[MAXNODE][4];
int f[MAXNODE];
long long matrix[MAXNODE][MAXNODE];
bool jud[MAXNODE];
int tot;
void init()
{
tot = 1;
memset(ch[0],0,sizeof(ch[0]));
memset(matrix,0,sizeof(matrix));
}
int idx(char c)
{
if(c == 'A') return 0;
if(c == 'T') return 1;
if(c == 'C') return 2;
if(c == 'G') return 3;
}
void insert(char *s)
{
int u = 0,n = strlen(s);
for(int i = 0;i < n;i++)
{
int c = idx(s[i]);
if(!ch[u][c])
{
memset(ch[tot],0,sizeof(ch[tot]));
jud[tot] = false;
ch[u][c] = tot++;
}
u = ch[u][c];
}
jud[u] = true;
}
void getFail()
{
queue<int> q;
f[0] = 0;
for(int c = 0;c < 4;c++)
{
int u = ch[0][c];
if(u)
{
f[u] = 0;
q.push(u);
if(!jud[u]) matrix[0][u]++;
}
else matrix[0][0]++;
}
while(!q.empty())
{
int r = q.front();q.pop();
for(int c = 0;c < 4;c++)
{
int u = ch[r][c];
if(!u)
{
ch[r][c] = ch[f[r]][c];
if(!jud[ch[r][c]]) matrix[r][ch[r][c]]++;
continue;
}
q.push(u);
f[u] = ch[f[r]][c];
jud[u] = jud[u] || jud[f[u]];
if(!jud[u]) matrix[r][u]++;
}
}
}
void matrixmul(const long long a[105][105],const long long b[105][105],long long c[105][105])
{
long long t[105][105];
memset(t,0,sizeof(t));
for(int i = 0;i < tot;i++)
for(int j = 0;j < tot;j++)
for(int k = 0;k < tot;k++)
t[i][j] = t[i][j] + a[i][k]*b[k][j] % 100000;
for(int i = 0;i < tot;i++)
for(int j = 0;j < tot;j++)
c[i][j] = t[i][j];
}
int deal(int n)
{
long long ans[105][105];
memset(ans,0,sizeof(ans));
for(int i = 0;i < tot;i++) ans[i][i] = 1ll;
while(n)
{
if(n & 1) matrixmul(ans,matrix,ans);
matrixmul(matrix,matrix,matrix);
n>>=1;
}
int num = 0;
for(int i = 0;i < tot;i++) num = (num + ans[0][i]) % 100000;
return num;
}
} tree;
int main()
{
cin.sync_with_stdio(false);
cin>>m>>n;
tree.init();
for(int i = 1;i <= m;i++)
{
cin>>s;
tree.insert(s);
}
tree.getFail();
cout<<tree.deal(n)<<endl;
}