/* ID: wuqi9395@126.com PROG: LANG: C++ */ #include<map> #include<set> #include<queue> #include<stack> #include<cmath> #include<cstdio> #include<vector> #include<string> #include<fstream> #include<cstring> #include<ctype.h> #include<iostream> #include<algorithm> #define INF (1<<30) #define PI acos(-1.0) #define mem(a, b) memset(a, b, sizeof(a)) #define rep(i, n) for (int i = 0; i < n; i++) #define debug puts("===============") typedef long long ll; typedef unsigned long long ULL; using namespace std; const int maxn = 65; const int maxm = 65; struct Matrix { int n, m; ULL a[maxn][maxm]; void clear() { n = m = 0; memset(a, 0, sizeof(a)); } Matrix operator * (const Matrix &b) const { //实现矩阵乘法 Matrix tmp; tmp.n = n; tmp.m = b.m; for (int i = 0; i < n; i++) for (int j = 0; j < b.m; j++) tmp.a[i][j] = 0; for (int i = 0; i < n; i++) for (int j = 0; j < m; j++) { if (!a[i][j]) continue; for (int k = 0; k < b.m; k++) tmp.a[i][k] += a[i][j] * b.a[j][k]; } return tmp; } Matrix operator + (const Matrix &b) const { Matrix tmp; tmp.n = n; tmp.m = m; for (int i = 0; i < n; i++) for (int j = 0; j < m; j++) tmp.a[i][j] = a[i][j] + b.a[i][j]; return tmp; } void Copy(const Matrix &b) { n = b.n, m = b.m; for (int i = 0; i < n; i++) for(int j = 0; j < m; j++) a[i][j] = b.a[i][j]; } void unit(int sz) { n = m = sz; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) a[i][j] = 0; a[i][i] = 1; } } } A, res; const int maxnode = 30 * 26; const int charset = 26; struct ACAutomaton { int ch[maxnode][charset]; int fail[maxnode]; int Q[maxnode]; int val[maxnode]; int sz; int ID[128]; void init() { fail[0] = 0; for (int i = 0; i < charset; i++) ID[i + 'a'] = i; } void reset() { sz = 1; memset(ch[0], 0, sizeof(ch[0])); } void Insert(char* s, int key) { int u = 0; for (; *s; s++) { int c = ID[*s]; if (!ch[u][c]) { memset(ch[sz], 0, sizeof(ch[sz])); val[sz] = 0; ch[u][c] = sz++; } u = ch[u][c]; } val[u] = key; } void Construct () { int *s = Q, *e = Q; for (int i = 0; i < charset; i++) { if (ch[0][i]) { *e++ = ch[0][i]; fail[ch[0][i]] = 0; } } while(s != e) { int u = *s++; if (val[fail[u]]) val[u] = 1; for (int i = 0; i < charset; i++) { int &v = ch[u][i]; if (v) { *e++ = v; fail[v] = ch[fail[u]][i]; } else { v = ch[fail[u]][i]; } } } } void work() { for (int i = 0; i < sz; i++) { for (int j = 0; j < charset; j++) { if (!val[i] && !val[ch[i][j]]) { A.a[ch[i][j]][i]++; } } } } } AC; Matrix Matrix_pow(Matrix A, ll k) { res.clear(); res.n = res.m = AC.sz; for (int i = 0; i < AC.sz; i++) res.a[i][i] = 1; while(k) { if (k & 1) res.Copy(res * A); A.Copy(A * A); k >>= 1; } return res; } void out() { for (int i = 0; i < A.n; i++) { for (int j = 0; j < A.m; j++) { printf("%2d ", res.a[i][j]); } cout << endl; } } Matrix Matrix_Bpow(Matrix A, ll k) { Matrix ans, I, tmp; ans.clear(); ans.n = ans.m = A.n; I.unit(A.n); tmp.unit(A.n); while(k > 0) { if (k & 1) ans.Copy(ans * A + tmp); tmp.Copy(tmp * (I + A)); A.Copy(A * A); k >>= 1; } return ans; } int main () { int n; ll l; char str[10]; AC.init(); while(~scanf("%d%I64d", &n, &l)) { A.clear(); AC.reset(); for (int i = 0; i < n; i++) { scanf("%s", str); AC.Insert(str, 1); } int sz = AC.sz; A.n = A.m = sz; AC.Construct(); AC.work(); //分治法 res = Matrix_Bpow(A, l + 1); //out(); /* 构造矩阵 //得到1 + A + A^2 + A^3 + ... + A^l for (int i = 0; i < sz; i++) A.a[i][i + sz] = A.a[i + sz][i + sz] = 1; res = Matrix_pow(A, l + 1); */ ULL ans = 0; for (int i = 0; i < sz; i++) ans += res.a[i][0]; ans--; //得到1 + 26 + 26^2 + ... + 26^l A.clear(); A.n = A.m = 2; A.a[0][0] = 26, A.a[0][1] = A.a[1][1] = 1; A = Matrix_pow(A, l + 1); ULL tot = A.a[0][1] - 1; printf("%I64u\n", tot - ans); } return 0; }
HDU 2243 考研路茫茫――单词情结 (AC自动机 + dp),布布扣,bubuko.com
HDU 2243 考研路茫茫――单词情结 (AC自动机 + dp)
原文地址:http://blog.csdn.net/sio__five/article/details/38707549