DNA Sequence
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 16494 | Accepted: 6380 |
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
AC自动机+DP.
先建树,再推出递推矩阵。
n很大,需要使用矩阵快速幂加速。
由于数据范围(模式串)很小,可以用数组模拟链表。
搞了一下午。。。终于可以安心复习(预习)大物了
详细题解:http://www.cppblog.com/menjitianya/archive/2014/07/10/207604.html
#include <cstdio>
#include <iostream>
#include <string.h>
#include <string>
#include <queue>
using namespace std;
typedef long long ll;
const int maxn=111;
const ll mod=1e5;
int tree[maxn][4],fail[maxn],flag[maxn],num;
int id['Z'];
char a[15];
struct Matrix {
ll a[111][111];
};
void insert (string s,int len) {
int i,j,p=0;
for (i=0;i<len;i++) {
int pos=id[s[i]];
if (!tree[p][pos]) {
tree[p][pos]=++num;
}
p=tree[p][pos];
}
flag[p]=1;
}
void buildfail() {
queue<int> q;
int i;
for (i=0;i<4;i++) {
if (tree[0][i]) {
q.push(tree[0][i]);
fail[tree[0][i]]=0;
}
}
while (!q.empty()) {
int now=q.front();
q.pop();
if (flag[fail[now]]) flag[now]=1;
for (i=0;i<4;i++) {
int to=tree[now][i];
if (to) {
fail[to]=tree[fail[now]][i];
q.push(to);
} else tree[now][i]=tree[fail[now]][i];
}
}
}
Matrix buildmap() {
int i,j;
Matrix map;
for (i=0;i<=num;i++)
for (j=0;j<=num;j++)
map.a[i][j]=0;
for (i=0;i<=num;i++)
for (j=0;j<4;j++)
if (!flag[tree[i][j]]&&!flag[i])
map.a[i][tree[i][j]]++;
/* for (i=0;i<=num;i++) {
for (j=0;j<=num;j++) {
cout << map.a[i][j] << ' ';
}
cout << '\n';
}*/
return map;
}
Matrix operator*(const Matrix &x,const Matrix &y) {
Matrix ans;
int i,j,k;
for (i=0;i<=num;i++) {
for (j=0;j<=num;j++) {
ans.a[i][j]=0;
for (k=0;k<=num;k++) {
ans.a[i][j]+=x.a[i][k]*y.a[k][j];
ans.a[i][j]%=mod;
}
}
}
return ans;
}
Matrix fastpower(Matrix s,ll index) {
Matrix ans,base=s;
ll k=index;
int i,j;
for (i=0;i<=num;i++)
for (j=0;j<=num;j++)
if (i==j) ans.a[i][j]=1; else ans.a[i][j]=0;
while (k) {
if (k%2) ans=ans*base;
base=base*base;
k/=2;
}
return ans;
}
int main() {
int n,i,j;
ll m;
scanf("%d%lld",&n,&m);
id['A']=0;id['T']=1;id['C']=2;id['G']=3;
num=0;
memset(tree,0,sizeof(tree));
memset(flag,0,sizeof(flag));
memset(fail,0,sizeof(fail));
for (i=1;i<=n;i++) {
scanf("%s",a);
insert(a,strlen(a));
}
buildfail();
buildmap();
Matrix ans=fastpower(buildmap(),m);
ll tot=0;
for (i=0;i<=num;i++) {
tot+=ans.a[0][i];
tot%=mod;
}
printf("%lld\n",tot);
return 0;
}