HDU2243 考研路茫茫——单词情结 AC自动机DP矩阵优化
2015-01-29 15:42
417 查看
传送门:点击打开链接
Total Submission(s): 3929 Accepted Submission(s): 1147
[align=left]Problem Description[/align]
背单词,始终是复习英语的重要环节。在荒废了3年大学生涯后,Lele也终于要开始背单词了。
一天,Lele在某本单词书上看到了一个根据词根来背单词的方法。比如"ab",放在单词前一般表示"相反,变坏,离去"等。
于是Lele想,如果背了N个词根,那这些词根到底会不会在单词里出现呢。更确切的描述是:长度不超过L,只由小写字母组成的,至少包含一个词根的单词,一共可能有多少个呢?这里就不考虑单词是否有实际意义。
比如一共有2个词根 aa 和 ab ,则可能存在104个长度不超过3的单词,分别为
(2个) aa,ab,
(26个)aaa,aab,aac...aaz,
(26个)aba,abb,abc...abz,
(25个)baa,caa,daa...zaa,
(25个)bab,cab,dab...zab。
这个只是很小的情况。而对于其他复杂点的情况,Lele实在是数不出来了,现在就请你帮帮他。
[align=left]Input[/align]
本题目包含多组数据,请处理到文件结束。
每组数据占两行。
第一行有两个正整数N和L。(0<N<6,0<L<2^31)
第二行有N个词根,每个词根仅由小写字母组成,长度不超过5。两个词根中间用一个空格分隔开。
[align=left]Output[/align]
对于每组数据,请在一行里输出一共可能的单词数目。
由于结果可能非常巨大,你只需要输出单词总数模2^64的值。
[align=left]Sample Input[/align]
[align=left]Sample Output[/align]
[align=left]Author[/align]
linle
题意:给出n个单词。问长度不超过m的串中,至少包含上述的至少一个单词的串的数目,对2^64取MOD
思路:这道题和POJ 2278比较相似,没有做过的请先参考/article/9437129.html
与POJ 2278最大的不同的,这道题要求得是长度不超过m的串。就要求得长度为1、2、3……m的符合要求串。可以参照POJ 2278的思路,先求出不符合的串,在用总数减去这个值,就得到了答案。下面设矩阵为A.中间会用到求A+A^2+A^3+……A^m【记为X】和26+26^2+26^3……+26^m次方的值。可以参考二分幂的方法。先求出(A+A^2+A^3……A^(m/2)【记为B】和A^(m/2)的值。那么X=(A^(m/2)+E)*B。E为单位阵。算数的也是同样的方法。将运算过程中的变量和矩阵的元素定义为unsigned
__int64,就能实现自动对2^64自动取MOD
代码:
考研路茫茫——单词情结
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 3929 Accepted Submission(s): 1147
[align=left]Problem Description[/align]
背单词,始终是复习英语的重要环节。在荒废了3年大学生涯后,Lele也终于要开始背单词了。
一天,Lele在某本单词书上看到了一个根据词根来背单词的方法。比如"ab",放在单词前一般表示"相反,变坏,离去"等。
于是Lele想,如果背了N个词根,那这些词根到底会不会在单词里出现呢。更确切的描述是:长度不超过L,只由小写字母组成的,至少包含一个词根的单词,一共可能有多少个呢?这里就不考虑单词是否有实际意义。
比如一共有2个词根 aa 和 ab ,则可能存在104个长度不超过3的单词,分别为
(2个) aa,ab,
(26个)aaa,aab,aac...aaz,
(26个)aba,abb,abc...abz,
(25个)baa,caa,daa...zaa,
(25个)bab,cab,dab...zab。
这个只是很小的情况。而对于其他复杂点的情况,Lele实在是数不出来了,现在就请你帮帮他。
[align=left]Input[/align]
本题目包含多组数据,请处理到文件结束。
每组数据占两行。
第一行有两个正整数N和L。(0<N<6,0<L<2^31)
第二行有N个词根,每个词根仅由小写字母组成,长度不超过5。两个词根中间用一个空格分隔开。
[align=left]Output[/align]
对于每组数据,请在一行里输出一共可能的单词数目。
由于结果可能非常巨大,你只需要输出单词总数模2^64的值。
[align=left]Sample Input[/align]
2 3 aa ab 1 2 a
[align=left]Sample Output[/align]
104 52
[align=left]Author[/align]
linle
题意:给出n个单词。问长度不超过m的串中,至少包含上述的至少一个单词的串的数目,对2^64取MOD
思路:这道题和POJ 2278比较相似,没有做过的请先参考/article/9437129.html
与POJ 2278最大的不同的,这道题要求得是长度不超过m的串。就要求得长度为1、2、3……m的符合要求串。可以参照POJ 2278的思路,先求出不符合的串,在用总数减去这个值,就得到了答案。下面设矩阵为A.中间会用到求A+A^2+A^3+……A^m【记为X】和26+26^2+26^3……+26^m次方的值。可以参考二分幂的方法。先求出(A+A^2+A^3……A^(m/2)【记为B】和A^(m/2)的值。那么X=(A^(m/2)+E)*B。E为单位阵。算数的也是同样的方法。将运算过程中的变量和矩阵的元素定义为unsigned
__int64,就能实现自动对2^64自动取MOD
代码:
#pragma comment(linker, "/STACK:102400000,102400000") #include<cstdio> #include<cstring> #define SIGMA_SIZE 26 #define maxn 40 #include<queue> #define uLL unsigned __int64 using namespace std; int ch[maxn][SIGMA_SIZE]; int val[maxn]; int last[maxn], f[maxn]; int cnt; inline int idx(char c) { return c - 97; } void insert(char s[]) { int len = strlen(s); int u = 0; for (int i = 0; i<len; i++) { int v = idx(s[i]); if (!ch[u][v]) ch[u][v] = ++cnt; u = ch[u][v]; } val[u] = 1; } struct Matrix { uLL g[maxn][maxn]; int r, c; Matrix operator * (const Matrix &b) const { Matrix res; res.r = r; res.c = b.c; memset(res.g, 0, sizeof(res.g)); for (int i = 0; i <= r; i++) for (int j = 0; j <= b.c; j++) for (int k = 0; k <= c; k++) res.g[i][j] += g[i][k] * b.g[k][j]; return res; } Matrix operator + (const Matrix &b) const { Matrix res; res.r = r; res.c = c; memset(res.g, 0, sizeof(g)); for (int i = 0; i <= r; i++) for (int j = 0; j <= c; j++) res.g[i][j] = g[i][j] + b.g[i][j]; return res; } }; Matrix ONE(int M) { Matrix res; res.r = M; res.c = M; memset(res.g, 0, sizeof(res.g)); for (int i = 0; i <= M; i++) res.g[i][i] = 1; return res; } Matrix ZERO(int M) { Matrix res; res.r = M; res.c = M; memset(res.g, 0, sizeof(res.g)); return res; } pair<Matrix, Matrix> bin(Matrix a, int k) { pair<Matrix, Matrix> tmp, res; if (k == 0) { return make_pair(ZERO(a.r), ONE(a.r)); } else if (k == 1) return make_pair(a, a); tmp = bin(a, k >> 1); res.first = (tmp.second + ONE(a.r))*tmp.first; res.second = tmp.second*tmp.second; if (k & 1) { res.second = res.second*a; res.first = res.first + res.second; } return res; } bool vis[maxn]; int mp[maxn][maxn]; void bfs() { memset(vis, 0, sizeof(vis)); vis[0] = 1; queue<int>q; q.push(0); while (!q.empty()) { int u = q.front(); q.pop(); for (int i = 0; i<26; i++) { int p = u; while (p&&!ch[p][i]) p = f[p]; p = ch[p][i]; if (val[p]) continue; if (last[p]) continue; mp[u][p]++; if (!vis[p]) q.push(p); vis[p] = 1; } } } pair<uLL, uLL> bin(uLL a, int k) { if (k == 1) return make_pair(a, a); else if (k == 0) return (make_pair(0, 1)); pair<uLL, uLL>tmp, res; tmp = bin(a, k >> 1); res.first = (tmp.second + 1)*tmp.first; res.second = tmp.second*tmp.second; if (k & 1) { res.second = res.second*a; res.first = res.first + res.second; } return res; } void slove(uLL m) { memset(mp, 0, sizeof(mp)); bfs(); Matrix tmp; tmp.r = cnt; tmp.c = cnt; for (int i = 0; i <= cnt; i++) for (int j = 0; j <= cnt; j++) tmp.g[i][j] = mp[i][j]; pair<Matrix, Matrix> res; res = bin(tmp, m); uLL ans = 0; for (int i = 0; i <= cnt; i++) ans += res.first.g[0][i]; ans = bin(26, m).first - ans; printf("%I64u\n", ans); } void getFail() { queue<int>q; f[0] = 0; for (int c = 0; c<SIGMA_SIZE; c++) { int u = ch[0][c]; if (u) { f[u] = 0; q.push(u); last[u] = 0; } } while (!q.empty()) { int r = q.front(); q.pop(); 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]]; } } } int main() { int n, m; while (~scanf("%d %d", &n, &m)) { memset(ch, 0, sizeof(ch)); memset(val, 0, sizeof(val)); cnt = 0; char s[15]; for (int i = 1; i <= n; i++) { scanf("%s", s); insert(s); } getFail(); slove(m); } return 0; }可能会栈溢出,所以我直接交了C++
相关文章推荐
- HDU2243 考研路茫茫——单词情结
- 【AC自动机】【矩阵乘法】【等比数列】hdu2243 考研路茫茫——单词情结
- hdu2243 考研路茫茫——单词情结 AC自动机+矩阵快速幂
- hdu2243 考研路茫茫——单词情结(AC自动机+矩阵快速幂)
- HDU2243 考研路茫茫——单词情结(AC自动机+矩阵快速幂+等比矩阵求和)
- [hdu2243][ac自动机]考研路茫茫——单词情结
- HDU2243 考研路茫茫——单词情结 AC自动机+矩阵连乘
- HDU2243 考研路茫茫——单词情结(AC自动机+矩阵快速幂)
- [hdu2243]考研路茫茫——单词情结(AC自动机+矩阵快速幂)
- hdu2243 考研路茫茫——单词情结 (AC自动机+矩阵快速幂)
- HDU2243 考研路茫茫——单词情结 [AC自动机+矩阵]
- hdu2243.考研路茫茫——单词情结(Trie图 && 矩阵乘法)
- hdu2243---考研路茫茫——单词情结(AC自动机+矩阵+二分)
- HDU2243--考研路茫茫——单词情结
- 【hdu2243】【AC自动机】【矩阵乘法】考研路茫茫——单词情结
- hdu2243考研路茫茫——单词情结 【AC自动机+动态规划+矩阵快速幂】
- HDU 2243 考研路茫茫——单词情结
- hdu 2243 考研路茫茫——单词情结(2013华师校赛 H题 Choose a password)
- HDU 2243 考研路茫茫——单词情结
- HDU 2243 考研路茫茫——单词情结 AC自动机 + 矩阵快速幂