(这道题是我的第一道动态矩阵。以前做过ac自动机,做过静态矩阵。于是很想做这道题。可是自己就是想不出来思路。后来是和芳哥一起讨论整理出的思路。非常非常感谢芳哥。。后来我写的时候,半个小时敲完,然后一直wa,发现有个bug,如(GA, AT)那么G后面的C转向状态0,但是我写的trie里面G后面没有C 。 于是我各种想办法。 这种时候,不要找度娘。 因为度娘告诉我很多我看不懂得方法。于是还是自己想。
解决方法:
1.在建失败指针里面if(p->ch[k]==NULL) p->ch[k] = p->fail->ch[k];
解决方法:
1.在建失败指针里面if(p->ch[k]==NULL) p->ch[k] = p->fail->ch[k];
2.在建矩阵里面if( t[i].ch[j]==NULL ) tmp[i][0]++;
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
const int maxn = 1009;
const double esp = 1e-6;
const __int64 mod = 100000;
__int64 tmp[109][109];
__int64 ans[109][109];
int cnt;
struct trie
{
trie *ch[4]; // 0A; 1C; 2G; 3T
//trie *jump[4];
trie *fail;
bool end;
int index;
void init()
{
memset(ch, NULL, sizeof(ch));
//memset(jump, NULL, sizeof(jump));
fail = NULL;
end = false;
index = cnt;
}
}t[109], *root;
void insert(char *str)
{
trie *p = root;
for(int i=0; str[i]; i++)
{
int k;
if(str[i]=='A') k = 0;
else if(str[i]=='C') k = 1;
else if(str[i]=='G') k = 2;
else k = 3;
if(p->ch[k]==NULL)
{
t[cnt].init();
p->ch[k] = &t[cnt++];
}
p = p->ch[k];
}
p->end = true;
}
queue<trie*>q;
void build_fail()
{
q.push(root);
root->fail = root;
while(!q.empty())
{
trie *p = q.front();
q.pop();
for(int k=0; k<4; k++)
if(p->ch[k]!=NULL)
{
q.push(p->ch[k]);
if(p==root)
{
p->ch[k]->fail = root;
if( p->ch[k]->fail->end == true )
p->ch[k]->end = true;
continue;
}
trie *tmp = p->fail;
while( tmp!=root && tmp->ch[k]==NULL)
tmp = tmp->fail;
if(tmp->ch[k]) p->ch[k]->fail = tmp->ch[k];
else p->ch[k]->fail = root;
if( p->ch[k]->fail->end == true )
p->ch[k]->end = true;
}
else p->ch[k] = p->fail->ch[k];
}
}
void mulans()
{
__int64 b[cnt][cnt];
for(int i=0; i<cnt; i++)
{
for(int j=0; j<cnt; j++)
{
b[i][j] = 0;
for(int k=0; k<cnt; k++)
{
b[i][j] += ans[i][k]*tmp[k][j];
b[i][j] %= mod;
}
}
}
for(int i=0; i<cnt; i++)
{
for(int j=0; j<cnt; j++)
ans[i][j] = b[i][j];
}
}
void multmp()
{
__int64 b[cnt][cnt];
for(int i=0; i<cnt; i++)
{
for(int j=0; j<cnt; j++)
{
b[i][j] = 0;
for(int k=0; k<cnt; k++)
{
b[i][j] += tmp[i][k]*tmp[k][j];
b[i][j] %= mod;
//cout<<"tmp "<<i<<' '<<j<<' '<<b[i][j]<<endl;
}
}
}
for(int i=0; i<cnt; i++)
{
for(int j=0; j<cnt; j++)
tmp[i][j] = b[i][j];
}
}
int main()
{
int m, n;
char str[12];
cnt = 0;
t[cnt].init();
root = &t[cnt++];
scanf("%d%d", &m, &n);
while(m--)
{
scanf("%s", str);
insert(str);
}
build_fail();
memset(tmp, 0, sizeof(tmp));
for(int i=0; i<cnt; i++)
if( t[i].end == false )
{
//cout<<i<<' '<<cnt<<endl;
for(int j=0; j<4; j++)
{
if( t[i].ch[j]==NULL )
{
tmp[i][0]++;
tmp[i][0] %= mod;
}
else if( t[i].ch[j]->end == false )
{
tmp[i][ t[i].ch[j]->index ]++;
tmp[i][ t[i].ch[j]->index ] %= mod;
}
}
}
for(int i=0; i<cnt; i++)
{
for(int j=0; j<cnt; j++)
ans[i][j] = i==j;
}
//cout<<ans[0][0]<<" ----\n";
while(n)
{
if(n&1) mulans();
multmp();
n/=2;
}
__int64 ok = 0;
for(int i=0; i<cnt; i++)
ok = (ok+ans[0][i])%mod;
printf("%I64d\n", ok);
return 0;
}