地址:http://poj.org/problem?id=2778
思路:同样是 AC自动机+矩阵快速幂。。
Code :
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
typedef long long LL;
const int MAX_M=15;
const int max_tot = 105; //最大编号
const int max_size = 4; //组成元素个数##
const int mod = 1e5;
char s[15];
int chr[30];
struct mac {
LL a[max_tot][max_tot];
int len;
mac() {
len = 0;
memset(a, 0, sizeof(a));
}
mac operator*(const mac &c)const {
mac t;
t.len = len;
for (int i = 0; i < len; ++i)
for (int j = 0; j < len; ++j) {
t.a[i][j] = 0;
for (int k = 0; k < len; ++k)
t.a[i][j] += a[i][k] * c.a[k][j];
t.a[i][j] %= mod;
}
return t;
}
};
struct AC {
int trie[max_tot][max_size];
int val[max_tot];
int fail[max_tot];
int size;
void Clear()
{
memset(trie, 0, sizeof(trie));
memset(val, 0, sizeof(val));
memset(fail,0,sizeof(fail));
size = 1;
}
void insert(char *str)
{
int k = 0;
for (int i = 0; str[i]; ++i)
{
int x = chr[str[i]-'A'];
if (!trie[k][x]){
trie[k][x] = size++;
}
k = trie[k][x];
}
val[k] = 1;
}
void GetFail()
{
queue<int> Q;
for (int i = 0; i < max_size; ++i)
if(trie[0][i]) Q.push(trie[0][i]);
while (!Q.empty()) {
int r=Q.front(),k; Q.pop();
if(val[fail[r]]) val[r]=1;
for (int i = 0; i < max_size; ++i)
{
k = trie[r][i];
if (k) {
Q.push(k);
fail[k] = trie[fail[r]][i];
}else trie[r][i] = trie[fail[r]][i];
}
}
}
}ac;
mac Pow(mac a, LL b){
mac ans;
ans.len = a.len;
for (int i = 0; i < a.len; ++i)
ans.a[i][i] = 1;
while (b) {
if (b & 1) ans = ans*a;
a = a * a;
b >>= 1;
}
return ans;
}
int main()
{
chr['A'-'A']=0; chr['C'-'A']=1; chr['T'-'A']=2; chr['G'-'A']=3;
LL m,n;
while(~scanf("%lld%lld",&m,&n)){
ac.Clear();
for (int i = 0; i < m; ++i)
{
scanf("%s",s);
ac.insert(s);
}
ac.GetFail();
mac ans=mac();
ans.len = ac.size;
for (int i = 0; i < ac.size; ++i)
for (int j = 0; j < max_size; ++j)
{
int u = ac.trie[i][j];
if (!ac.val[u]) ++ans.a[i][u];
}
ans = Pow(ans, n);
LL sum = 0;
for (int i = 0; i < max_tot; ++i)
sum = (sum + ans.a[0][i]) % mod;
printf("%lld\n",sum);
}
return 0;
}