poj

链接:https://vjudge.net/problem/POJ-2778
思路:看到数据范围就大概知道是个矩阵的题目了,联想到camp里面吃豆豆那个用矩阵倍增加速的题目,其实这个题简单多了,原因是因为起点固定了且算的是总方案数,那么我们考虑自动机上每个状态能走到哪些状态,然后在矩阵上把这些值变为1,然后矩阵快速幂一下,得到的就是从一个点到另一个点走n步的总方案数(离散数学中的邻接矩阵的应用讲过)。因为起点从0开始,所以只用把那一行全部加起来即可得到答案。

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133

#include <cstring>
#include <queue>

using namespace std;

const int maxnode = 120;
const int sigma_size = 4;
typedef long long ll;
const ll mod = 1e5;
int n, m;
char str[20][50];

int ch[maxnode][sigma_size];
int val[maxnode];
int f[maxnode];
int last[maxnode];
int sz;

struct {
ll v[110][110];
Martix(){
memset(v, 0, sizeof(v));
}
};

Martix operator*(const Martix &a ,const Martix &b){
Martix c;
for(int i = 0; i < sz; i++){
for(int j = 0; j < sz; j++){
for(int k = 0; k < sz; k++){
c.v[i][j] = (c.v[i][j] + a.v[i][k] * b.v[k][j]) % mod;
}
}
}
return c;
}

void init(){
sz = 1;
memset(ch[0], 0, sizeof(ch[0]));
}

int idx(char c) {
if(c == 'A')return 0;
if(c == 'G')return 1;
if(c == 'C')return 2;
return 3;
}

void insert(char *s,int v = 1){
int n = strlen(s);
int u = 0;
for (int i = 0; i < n; i++){
int c = idx(s[i]);
if (!ch[u][c]){
ch[u][c] = sz;
memset(ch[sz], 0, sizeof(ch[sz]));
val[sz++] = 0;
}
u = ch[u][c];
}
val[u] = v;
}

void getfail() {
queue<int> q;
f[0] = 0;
for (int i = 0; i < sigma_size; i++) {
int u = ch[0][i];
if (u) {
f[u] = last[u] = 0;
q.push(u);
}
}
while (!q.empty()) {
int r = q.front();
q.pop();
val[r] |= val[f[r]];
for (int c = 0; c < sigma_size; c++) {
int u = ch[r][c];
if (!u) {
ch[r][c] = ch[f[r]][c];
continue;
}
q.push(u);
int v = f[r];
while (v && !ch[v][c])v = f[v];
f[u] = ch[v][c];
last[u] = val[f[u]] ? f[u] : last[f[u]];
}
}
}


Martix pow_mod(Martix &q, ll w){
Martix ret = q;
w--;
while(w){
if(w & 1)ret = ret * q;
q = q * q;
w >>= 1;
}
return ret;
}

int main(){
while(~scanf("%d %d", &m, &n)) {
init();
for (int i = 1; i <= m; i++) {
scanf("%s", str[i]);
insert(str[i]);
}

getfail();
Martix x;

for (int i = 0; i < sz; i++) {
if(val[i])continue;
for(int j = 0; j < sigma_size; j++){
if(!val[ch[i][j]])x.v[i][ch[i][j]]++;
}
}
x = pow_mod(x, n);
ll ans = 0;
for(int i = 0; i < sz; i++){
ans += x.v[0][i];
if(ans >= mod) ans -= mod;
}
printf("%lldn", ans);
}
return 0;
}