http://acm.hdu.edu.cn/showproblem.php?pid=2604
题意是找出长度为n的,不包含“fmf”或“fff”的字符串的个数。
这题我是直接套用之前的ac自动机的模板的,构造出自动机,然后利用矩阵快速幂求出结果。当然,这题可以直接推出递推公式,然后再套入矩阵中。复杂度O(m^2 log n),其中m是矩阵大小,n是要求计算的长度。
代码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <iostream> 5 6 using namespace std; 7 8 const int MS = 20; 9 int CS = MS; 10 int MOD = 30; 11 12 struct Mat { 13 int val[MS][MS]; 14 Mat(int u = 0) { 15 for (int i = 0; i < CS; i++) { 16 for (int j = 0; j < CS; j++) { 17 val[i][j] = 0; 18 } 19 val[i][i] = u % MOD; 20 } 21 } 22 void print() { 23 puts("Debug:"); 24 for (int i = 0; i < CS; i++) { 25 for (int j = 0; j < CS; j++) { 26 cout << val[i][j] << ' '; 27 } 28 cout << endl; 29 } 30 puts("~~~~~~"); 31 } 32 } Base, op; 33 34 Mat operator + (Mat &a, Mat &b) { 35 Mat ret; 36 for (int i = 0; i < CS; i++) { 37 for (int j = 0; j < CS; j++) { 38 ret.val[i][j] = (a.val[i][j] + b.val[i][j]) % MOD; 39 } 40 } 41 return ret; 42 } 43 44 Mat operator * (Mat &a, Mat &b) { 45 Mat ret = Mat(); 46 for (int i = 0; i < CS; i++) { 47 for (int k = 0; k < CS; k++) { 48 if (a.val[i][k]) { 49 for (int j = 0; j < CS; j++) { 50 ret.val[i][j] += a.val[i][k] * b.val[k][j]; 51 ret.val[i][j] %= MOD; 52 } 53 } 54 } 55 } 56 return ret; 57 } 58 59 Mat operator ^ (Mat &a, int p) { 60 Mat t = a; 61 Mat ret = Mat(1); 62 while (p > 0) { 63 if (p & 1) ret = ret * t; 64 t = t * t; 65 p >>= 1; 66 } 67 return ret; 68 } 69 70 const int kind = 2; 71 const int N = 10; 72 int root, cntNode; 73 74 struct Node { 75 int c[kind]; 76 int fail; 77 bool end; 78 void init() { 79 memset(c, -1, sizeof(c)); 80 fail = -1; 81 end = false; 82 } 83 } node[N]; 84 int Q[N], qh, qt; 85 86 void init() { 87 root = cntNode = 0; 88 node[root].init(); 89 } 90 91 void insert(char *s) { 92 int p = root, idx; 93 while (*s) { 94 idx = (*s == 'f'); 95 if (node[p].c[idx] == -1) { 96 node[++cntNode].init(); 97 node[p].c[idx] = cntNode; 98 } 99 p = node[p].c[idx]; 100 s++; 101 } 102 node[p].end = true; 103 } 104 105 void buildMat() { 106 op = Mat(); 107 Base = Mat(); 108 Base.val[0][0] = 1; 109 qh = qt = 1; 110 Q[qt++] = root; 111 while (qh < qt) { 112 int u = Q[qh++]; 113 for (int i = 0; i < kind; i++) { 114 int c = node[u].c[i]; 115 if (~c) { 116 if (u == root) { 117 node[c].fail = root; 118 } else { 119 node[c].fail = node[node[u].fail].c[i]; 120 if (node[node[c].fail].end) node[c].end = true; 121 } 122 Q[qt++] = c; 123 } else { 124 if (u == root) { 125 node[u].c[i] = root; 126 } else { 127 node[u].c[i] = node[node[u].fail].c[i]; 128 } 129 } 130 } 131 } 132 for (int i = 0; i < CS; i++) { 133 if (node[i].end) continue; 134 for (int j = 0; j < kind; j++) { 135 int t = node[i].c[j]; 136 if (node[t].end) continue; 137 op.val[i][t]++; 138 } 139 } 140 } 141 142 void PRE() { 143 char *str[2] = { "fmf", "fff"}; 144 init(); 145 insert(str[0]); 146 insert(str[1]); 147 CS = cntNode + 1; 148 buildMat(); 149 } 150 151 int main() { 152 int n; 153 PRE(); 154 // op.print(); 155 while (cin >> n >> MOD) { 156 Base = op; 157 Base = Base ^ n; 158 // Base.print(); 159 int ans = 0; 160 for (int i = 0; i < CS; i++) { 161 ans += Base.val[0][i]; 162 ans %= MOD; 163 } 164 cout << ans << endl; 165 } 166 return 0; 167 }
——written by Lyon