LA3942 Remember the Word(Trie+DP)
来源:互联网 发布:联通 套餐 4g数据副卡 编辑:程序博客网 时间:2024/09/21 06:18
题意:给出一个字符串(长度最长为300000)和n个单词,n不会超过4000,单词长度不会超过100,求字符串能由n个单词构成的个数,如果个数超过20071027,就对其求模
思路:先用n个单词构成Trie,d(i)=sum(d(i+len(x)),其中x是s[i..L]的前缀
在用dp时,先有记忆化的递归,但是当字符串长度为最长时,而单词长度比较短,而又能够构成字符串。例如如果字符串由300000个b组成,单词有2个,分别为b和bb,在用递归时,可能造成栈超过其深度限制。
具体代码如下:(这段代码可能会造成栈深度过深,抛出异常)
#include <iostream>#include <cstring>#include <string>#include <cstdio>using namespace std;const int N = 400010;const int MAX_CHILD_NUM = 26;const int WORD_LEN = 110;const int MOD = 20071027;int ch[N][MAX_CHILD_NUM];int val[N];int cnt;int dp[N];class Trie{public: void init() { memset(ch, 0x00, sizeof(ch)); memset(val, 0x00, sizeof(val)); memset(dp, 0xff, sizeof(dp)); cnt = 0; } void insert(string s) { int u = 0; for (int i = 0; i < s.length(); i++) { int idx = s[i] - 'a'; if (!ch[u][idx]) { cnt++; ch[u][idx] = cnt; val[cnt] = 0; } u = ch[u][idx]; } val[u] = 1; } int find(string s) { int u = 0; int len = s.length(); int& ans = dp[len] ; if (len == 0) { return ans = 1; } if (ans >= 0) return ans; ans = 0; for (int i = 0; i < len; i++) { int idx = s[i] - 'a'; u = ch[u][idx]; if (u == 0) break; if (val[u]) { ans += find(s.substr(i + 1)); ans %= MOD; } } return ans; }};char buf[N], tmp[WORD_LEN];Trie trie;int main(){#ifndef ONLINE_JUDGE freopen("d:\\program\\clion\\spoj.txt", "r", stdin);#endif string s; int cas = 1; while (scanf("%s", buf) == 1) { trie.init(); int n; scanf("%d", &n); for (int i = 0; i < n; i++) { string word; scanf("%s", tmp); word = tmp; trie.insert(word); } s = buf; int ans = trie.find(s); printf("Case %d: %d\n", cas++, ans); } return 0;}
换成dp的递推式后,在用函数实现时,将字符串string作为参数超时,换成引用 后accepted,因为字符串比较长时,涉及到大量的复制,用引用就不会
代码如下:
#include <iostream>#include <cstring>#include <string>#include <cstdio>#include <exception>using namespace std;const int N = 400010;const int MAX_CHILD_NUM = 26;const int WORD_LEN = 110;const int MOD = 20071027;int ch[N][MAX_CHILD_NUM];int val[N];int cnt;int dp[N];class Trie{public: void init() { memset(ch, 0x00, sizeof(ch)); memset(val, 0x00, sizeof(val)); memset(dp, 0xff, sizeof(dp)); cnt = 0; } void insert(string s) { int u = 0; for (int i = 0; i < s.length(); i++) { int idx = s[i] - 'a'; if (!ch[u][idx]) { cnt++; ch[u][idx] = cnt; val[cnt] = 0; } u = ch[u][idx]; } val[u] = 1; } int find(string& s) { int len = s.length(); for (int i = 0; i <= len; i++) { cal(s, len - i); } return dp[0]; }private: void cal(string& s, int start) { int u = 0; int len = s.length(); int& ans = dp[start]; if (start == len) { ans = 1; return; } ans = 0; for (int i = start; i < len; i++) { int idx = s[i] - 'a'; u = ch[u][idx]; if (u == 0) break; if (val[u]) { ans += dp[i + 1]; ans %= MOD; } } }};char buf[N], tmp[WORD_LEN];Trie trie;int main(){#ifndef ONLINE_JUDGE freopen("d:\\program\\clion\\spoj.txt", "r", stdin);#endif string s; int cas = 1; while (scanf("%s", buf) == 1) { trie.init(); int n; scanf("%d", &n); for (int i = 0; i < n; i++) { string word; scanf("%s", tmp); word = tmp; trie.insert(word); } s = buf; int ans = trie.find(s); printf("Case %d: %d\n", cas++, ans); } return 0;}
将变量封装到类中,代码如下:
#include <iostream>#include <cstring>#include <string>#include <cstdio>#include <exception>using namespace std;const int N = 400010;const int MAX_CHILD_NUM = 26;const int WORD_LEN = 110;const int MOD = 20071027;class Trie{public: void init() { memset(ch, 0x00, sizeof(ch)); memset(val, 0x00, sizeof(val)); memset(dp, 0xff, sizeof(dp)); cnt = 0; } void insert(string s) { int u = 0; for (int i = 0; i < s.length(); i++) { int idx = s[i] - 'a'; if (!ch[u][idx]) { cnt++; ch[u][idx] = cnt; val[cnt] = 0; } u = ch[u][idx]; } val[u] = 1; } int find(string& s) { int len = s.length(); for (int i = 0; i <= len; i++) { cal(s, len - i); } return dp[0]; }private: void cal(string& s, int start) { int u = 0; int len = s.length(); int& ans = dp[start]; if (start == len) { ans = 1; return; } ans = 0; for (int i = start; i < len; i++) { int idx = s[i] - 'a'; u = ch[u][idx]; if (u == 0) break; if (val[u]) { ans += dp[i + 1]; ans %= MOD; } } }private: int ch[N][MAX_CHILD_NUM]; int val[N]; int cnt; int dp[N];};char buf[N], tmp[WORD_LEN];Trie trie;int main(){#ifndef ONLINE_JUDGE freopen("d:\\program\\clion\\spoj.txt", "r", stdin);#endif string s; int cas = 1; while (scanf("%s", buf) == 1) { trie.init(); int n; scanf("%d", &n); for (int i = 0; i < n; i++) { string word; scanf("%s", tmp); word = tmp; trie.insert(word); } s = buf; int ans = trie.find(s); printf("Case %d: %d\n", cas++, ans); } return 0;}
0 0
- LA3942 remember the word trie+dp
- LA3942 Remember the Word(Trie+DP)
- 【LA3942】Remember the Word【Trie】【计数DP】
- LA3942 Remember the Word(Trie+DP)
- [Trie树][dp] LA3942 Remember the Word
- Remember the Word,LA3942(Trie树+DP)
- [Trie树][dp] LA3942 Remember the Word 真·解法
- Remember the Word LA3942
- 【Trie的模板】例题11 LA3942 Remember the Word(字典树+dp)
- Uva1401/LA3942 Remember the Word(trie模板)
- LA3942 Remember the Word(字典树+DP)
- LA 3942 Remember the Word(Trie+DP)
- UVA 1401 - Remember the Word(Trie+DP)
- uva 1401 Remember the Word ( Trie + DP )
- UVA 1401 Remember the Word (trie + dp)
- UVa 1401 Remember the Word(Trie+DP)
- UVALive - 3942 Remember the Word(trie + dp)
- Remember the Word (trie)
- 基于版面排版设计的一个新闻类网站构建
- 赠维敏
- redis安装,启动
- 解决Spring框架的Dao层改用@Repository注解,无法使用JdbcDaoSupport的问题
- [19]CSS3 过渡效果
- LA3942 Remember the Word(Trie+DP)
- 2016.1.28日记
- Mac的vim下解决^M的问题!
- C++的链表操作
- windows下,源码配置Laravel5.3
- 一种新型的数据平滑滤波算法
- 迭代字典中的key和value
- Linux下使用samba工具共享文件
- final、finally和finalize的区别