例题3.11 背单词 LA3942
来源:互联网 发布:2017下半年网络流行词 编辑:程序博客网 时间:2024/06/06 09:08
1.题目描述:点击打开链接
2.解题思路:本题利用Trie+dp解决。首先,令d(i)表示从字符i开始的字符串(即后缀S[i...L])的分解方案数,那么d(i)=d(i+len(x)|单词x是S[i..L]的前缀)。如果我们枚举单词,然后判断它是否为S[i...L]的前缀,时间无法承受。所以可以考虑事先把所有的单词存入Trie,然后试着在Trie中查找S[i...L]。查找时,如果找到了一个单词结点,就把它的序号记下来,这样就找到了一个单词x,最多只需要100次比较就能找到所有的x。
3.代码:
#include<iostream>#include<algorithm>#include<cassert>#include<string>#include<sstream>#include<set>#include<bitset>#include<vector>#include<stack>#include<map>#include<queue>#include<deque>#include<cstdlib>#include<cstdio>#include<cstring>#include<cmath>#include<ctime>#include<cctype>#include<functional>#pragma comment(linker, "/STACK:1024000000,1024000000")using namespace std;#define me(s) memset(s,0,sizeof(s))#define rep(i,n) for(int i=0;i<(n);i++)typedef long long ll;typedef unsigned int uint;typedef unsigned long long ull;typedef pair <int, int> P;const int maxnode = 4000 * 100 + 10;const int sigma_size = 26;struct Trie{ int ch[maxnode][sigma_size]; int val[maxnode]; int sz; void clear() { sz = 1; memset(ch[0], 0, sizeof(ch[0])); } int idx(char c) { return c - 'a'; } void insert(const char *s, int v) { int u = 0, n = strlen(s); for(int i = 0; i < n; i++) { int c = idx(s[i]); if(!ch[u][c]) { memset(ch[sz], 0, sizeof(ch[sz])); val[sz] = 0; ch[u][c] = sz++; } u = ch[u][c]; } val[u] = v; } void find_prefixes(const char *s, int len, vector<int>& ans) { int u = 0; for(int i = 0; i < len; i++) { if(s[i] == '\0') break; int c = idx(s[i]); if(!ch[u][c]) break; u = ch[u][c]; if(val[u] != 0) ans.push_back(val[u]); } }};#include<cstdio>const int maxl = 300000 + 10; // 文本串最大长度const int maxw = 4000 + 10; // 单词最大个数const int maxwl = 100 + 10; // 每个单词最大长度const int MOD = 20071027;int d[maxl], len[maxw], S;char text[maxl], word[maxwl];Trie trie;int main(){ int kase = 1; while(scanf("%s%d", text, &S) == 2) { trie.clear(); for(int i = 1; i <= S; i++) { scanf("%s", word); len[i] = strlen(word); trie.insert(word, i); } memset(d, 0, sizeof(d)); int L = strlen(text); d[L] = 1; for(int i = L-1; i >= 0; i--) { vector<int> p; trie.find_prefixes(text+i, L-i, p); for(int j = 0; j < p.size(); j++) d[i] = (d[i] + d[i+len[p[j]]]) % MOD; } printf("Case %d: %d\n", kase++, d[0]); } return 0;}
0 0
- 例题3.11 背单词 LA3942
- LA3942 背单词(trie树&&简单动规)
- 背单词
- 背单词
- 背单词
- 背单词
- 背单词
- 背单词
- LA3942
- 每日背单词
- 如何背单词
- 背单词 考四级
- 背单词的方法
- MindMap背单词
- 背单词的方法
- 简易背单词
- 怎样背单词
- 颠覆背单词
- linux下的 fork vfork和clone函数
- 智力题(农民分金条问题)
- ACdream 1213 Matrix Multiplication
- Activity的启动模式
- HDU 3488--Tour【最小费用最大流 && 有向环最小权值覆盖 && 经典】
- 例题3.11 背单词 LA3942
- odoo(Openerp)如何在字段的on_change方法中动态返回domain
- fork()&&fork()||fork()
- Linux xargs 命令 【转载】
- Merge Two Sorted Lists
- pthread_create函数的详细讲解(包括向线程函数传递参数详解)
- DataStructure-8.1-二叉排序树
- 个人小结
- 【读书笔记】iOS-头文件导入-@class注意事项