hdu2243---考研路茫茫——单词情结(AC自动机+矩阵+二分)
2015-03-11 12:42
435 查看
首先对2^64取模的话,可以直接用unsigned long long,这样溢出部分就是取模后的结果了
方法类似POJ2778传送门
只不过这里要统计长度不超过m的方案
我们先统计出长度为m的所有方案,然后减去不包含这些串的方案,剩下就是至少包含一个串的方案了
设转移矩阵为A
相当于sum = A + A^2 + … A^m
f(m) = f(m / 2) * (1 + A ^(m / 2)) + (m & 1) ? A^m : 0
二分即可求出,但是不要写成递归的,不然会爆栈
对于求总数
f(m) = 1 + 26 + … + 26^m
f(m) = f(m - 1) * 26 + 1
[f(m), 1] = [26, 1; 0 1][f(m - 1), 1];
转移即可
方法类似POJ2778传送门
只不过这里要统计长度不超过m的方案
我们先统计出长度为m的所有方案,然后减去不包含这些串的方案,剩下就是至少包含一个串的方案了
设转移矩阵为A
相当于sum = A + A^2 + … A^m
f(m) = f(m / 2) * (1 + A ^(m / 2)) + (m & 1) ? A^m : 0
二分即可求出,但是不要写成递归的,不然会爆栈
对于求总数
f(m) = 1 + 26 + … + 26^m
f(m) = f(m - 1) * 26 + 1
[f(m), 1] = [26, 1; 0 1][f(m - 1), 1];
转移即可
/************************************************************************* > File Name: hdu2243.cpp > Author: ALex > Mail: zchao1995@gmail.com > Created Time: 2015年03月11日 星期三 10时27分24秒 ************************************************************************/ #include <map> #include <set> #include <queue> #include <stack> #include <vector> #include <cmath> #include <cstdio> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> #pragma comment (linker, "/STACK:1024000000, 1024000000") using namespace std; const double pi = acos(-1.0); const int inf = 0x3f3f3f3f; const double eps = 1e-15; typedef long long LL; typedef pair <int, int> PLL; const int MAX_NODE = 26; const int CHILD_NUM = 26; struct node { int k; unsigned long long mat[MAX_NODE][MAX_NODE]; void clear() { memset (mat, 0, sizeof(mat)); } }; stack <node> st; struct MARTIX { unsigned long long mat[MAX_NODE][MAX_NODE]; }A, E; MARTIX mul(MARTIX a, MARTIX b, int L) { MARTIX c; for (int i = 0; i < L; ++i) { for (int j = 0; j < L; ++j) { c.mat[i][j] = 0; for (int k = 0; k < L; ++k) { c.mat[i][j] += a.mat[i][k] * b.mat[k][j]; } } } return c; } MARTIX add(MARTIX a, MARTIX b, int L) { for (int i = 0; i < L; ++i) { for (int j = 0; j < L; ++j) { a.mat[i][j] += b.mat[i][j]; } } return a; } MARTIX martix_pow(MARTIX ret, int n, int L) { MARTIX ans; for (int i = 0; i < L; ++i) { for (int j = 0; j < L; ++j) { ans.mat[i][j] = (i == j); } } while (n) { if (n & 1) { ans = mul(ans, ret, L); } n >>= 1; ret = mul(ret, ret, L); } return ans; } /*MARTIX Binsearch(int k, int L) { if (k == 1) { return A; } if (k & 1) { MARTIX a = martix_pow(A, k >> 1, L); a = add(a, E, L); MARTIX b = Binsearch(k >> 1, L); a = mul(a, b, L); MARTIX c = martix_pow(A, k, L); a = add(a, c, L); return a; } else { MARTIX a = martix_pow(A, k >> 1, L); a = add(a, E, L); MARTIX b = Binsearch(k >> 1, L); a = mul(a, b, L); return a; } }*/ MARTIX work (int k, int L) { while (!st.empty()) { st.pop(); } int tmp = k; while (tmp != 1) { node x; x.clear(); x.k = tmp; st.push(x); tmp >>= 1; } MARTIX ans = A; while (!st.empty()) { node cur = st.top(); st.pop(); MARTIX a = martix_pow(A, cur.k / 2, L); a = add(a, E, L); ans = mul(ans, a, L); if (cur.k & 1) { MARTIX b = martix_pow(A, cur.k, L); ans = add(ans, b, L); } } return ans; } struct AC_Automation { int next[MAX_NODE][CHILD_NUM]; int fail[MAX_NODE]; int end[MAX_NODE]; int root, L; int newnode() { for (int i = 0; i < CHILD_NUM; ++i) { next[L][i] = -1; } end[L++] = 0; return L - 1; } void init() { L = 0; root = newnode(); } void Build_Trie(char buf[]) { int len = strlen(buf); int now = root; for (int i = 0; i < len; ++i) { if (next[now][buf[i] - 'a'] == -1) { next[now][buf[i] - 'a'] = newnode(); } now = next[now][buf[i] - 'a']; } end[now] = 1; } void Build_AC() { queue <int> qu; fail[root] = root; for (int i = 0; i < CHILD_NUM; ++i) { if (next[root][i] == -1) { next[root][i] = root; } else { fail[next[root][i]] = root; qu.push(next[root][i]); } } while (!qu.empty()) { int now = qu.front(); qu.pop(); if (end[fail[now]]) { end[now] = 1; } for (int i = 0; i < CHILD_NUM; ++i) { if (next[now][i] == -1) { next[now][i] = next[fail[now]][i]; } else { fail[next[now][i]] = next[fail[now]][i]; qu.push(next[now][i]); } } } } void solve (int n) { unsigned long long ans = 0; MARTIX tmp; tmp.mat[0][0] = 26; tmp.mat[0][1] = 1; tmp.mat[1][0] = 0; tmp.mat[1][1] = 1; tmp = martix_pow(tmp, n, 2); ans = tmp.mat[0][0] + tmp.mat[0][1] - 1; for (int i = 0; i < L; ++i) { for (int j = 0; j < L; ++j) { A.mat[i][j] = 0; E.mat[i][j] = (i == j); } } for (int i = 0; i < L; ++i) { if (end[i]) { continue; } for (int j = 0; j < CHILD_NUM; ++j) { if (!end[next[i][j]]) { ++A.mat[i][next[i][j]]; } } } MARTIX res = work(n, L); for (int i = 0; i < L; ++i) { ans -= res.mat[0][i]; } printf("%llu\n", ans); } }AC; char buf[15]; int main() { int m, n; while (~scanf("%d%d", &m, &n)) { AC.init(); for (int i = 1; i <= m; ++i) { scanf("%s", buf); AC.Build_Trie(buf); } AC.Build_AC(); AC.solve(n); } return 0; }
相关文章推荐
- [hdu2243][ac自动机]考研路茫茫——单词情结
- 【AC自动机】【矩阵乘法】【等比数列】hdu2243 考研路茫茫——单词情结
- [hdu2243]考研路茫茫——单词情结(AC自动机+矩阵快速幂)
- HDU2243 考研路茫茫——单词情结(AC自动机+矩阵快速幂+等比矩阵求和)
- HDU2243 考研路茫茫——单词情结 AC自动机DP矩阵优化
- HDU2243 考研路茫茫——单词情结 [AC自动机+矩阵]
- HDU2243 考研路茫茫——单词情结 AC自动机+矩阵连乘
- HDU2243 考研路茫茫——单词情结
- 【hdu2243】【AC自动机】【矩阵乘法】考研路茫茫——单词情结
- hdu2243考研路茫茫——单词情结 【AC自动机+动态规划+矩阵快速幂】
- hdu2243 考研路茫茫——单词情结 (AC自动机+矩阵快速幂)
- hdu2243.考研路茫茫——单词情结(Trie图 && 矩阵乘法)
- hdu2243 考研路茫茫——单词情结 AC自动机+矩阵快速幂
- HDU2243 考研路茫茫——单词情结(AC自动机+矩阵快速幂)
- HDU2243--考研路茫茫——单词情结
- hdu2243 考研路茫茫——单词情结(AC自动机+矩阵快速幂)
- hdu 2243 考研路茫茫——单词情结
- HDU 2243 考研路茫茫——单词情结(AC自动机+矩阵快速幂)
- hdu 2243 考研路茫茫——单词情结(AC自动机+矩阵快速幂)
- HDU 2243 考研路茫茫——单词情结 AC自动机 + 矩阵快速幂