uvaliva3942(trie树)
Posted yijiull
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了uvaliva3942(trie树)相关的知识,希望对你有一定的参考价值。
题目连接:https://vjudge.net/problem/UVALive-3942
trie树
dp[i]=sum(dp[i+len(x)]%mod;
dp[i]表示从字符i开始的字符串的分解方案方案数,x是s[i……L]的前缀
1 #include<cstdio> 2 #include<cstring> 3 const int maxnode=500010; 4 const int sigma=26; 5 const int N=300010; 6 const int mod=20071027; 7 int ch[maxnode][sigma]; 8 int val[maxnode]; 9 int sz; 10 inline int id(char c) {return c-‘a‘;} 11 12 void trie_init() 13 { 14 sz=1; 15 memset(ch[0],0,sizeof(ch[0])); 16 } 17 18 void inser(char *s,int v) 19 { 20 int u=0; 21 for(int i=0;s[i];i++) 22 { 23 int c=id(s[i]); 24 if(!ch[u][c]) 25 { 26 memset(ch[sz],0,sizeof(ch[sz])); 27 val[sz]=0; 28 ch[u][c]=sz++; 29 } 30 u=ch[u][c]; 31 } 32 val[u]=v; 33 } 34 int num,dp[N],st; 35 void query(char *s) 36 { 37 int u=0; 38 for(int i=0;s[i];i++) 39 { 40 int c=id(s[i]); 41 if(ch[u][c]) 42 { 43 u=ch[u][c]; 44 if(val[u]) num=(num+dp[st+i+1])%mod; // 45 } 46 else return; 47 } 48 } 49 int main() 50 { 51 char s[N],p[110]; 52 int k=0; 53 while(scanf("%s",s)!=EOF) 54 { 55 trie_init(); 56 int m; 57 scanf("%d",&m); 58 while(m--) 59 { 60 scanf("%s",p); 61 inser(p,1); 62 } 63 int len=strlen(s); 64 dp[len]=1; 65 for(int i=len-1;i>=0;i--) 66 { 67 num=0; 68 st=i; 69 query(&s[i]); 70 dp[i]=num; 71 } 72 printf("Case %d: %d\n",++k,dp[0]); 73 } 74 return 0; 75 }
lrj:
1 // LA3942 Remember the Word 2 // Rujia Liu 3 #include<cstring> 4 #include<vector> 5 using namespace std; 6 7 const int maxnode = 4000 * 100 + 10; 8 const int sigma_size = 26; 9 10 // 字母表为全体小写字母的Trie 11 struct Trie { 12 int ch[maxnode][sigma_size]; 13 int val[maxnode]; 14 int sz; // 结点总数 15 void clear() { sz = 1; memset(ch[0], 0, sizeof(ch[0])); } // 初始时只有一个根结点 16 int idx(char c) { return c - ‘a‘; } // 字符c的编号 17 18 // 插入字符串s,附加信息为v。注意v必须非0,因为0代表“本结点不是单词结点” 19 void insert(const char *s, int v) { 20 int u = 0, n = strlen(s); 21 for(int i = 0; i < n; i++) { 22 int c = idx(s[i]); 23 if(!ch[u][c]) { // 结点不存在 24 memset(ch[sz], 0, sizeof(ch[sz])); 25 val[sz] = 0; // 中间结点的附加信息为0 26 ch[u][c] = sz++; // 新建结点 27 } 28 u = ch[u][c]; // 往下走 29 } 30 val[u] = v; // 字符串的最后一个字符的附加信息为v 31 } 32 33 // 找字符串s的长度不超过len的前缀 34 void find_prefixes(const char *s, int len, vector<int>& ans) { 35 int u = 0; 36 for(int i = 0; i < len; i++) { 37 if(s[i] == ‘\0‘) break; 38 int c = idx(s[i]); 39 if(!ch[u][c]) break; 40 u = ch[u][c]; 41 if(val[u] != 0) ans.push_back(val[u]); // 找到一个前缀 42 } 43 } 44 }; 45 46 #include<cstdio> 47 const int maxl = 300000 + 10; // 文本串最大长度 48 const int maxw = 4000 + 10; // 单词最大个数 49 const int maxwl = 100 + 10; // 每个单词最大长度 50 const int MOD = 20071027; 51 52 int d[maxl], len[maxw], S; 53 char text[maxl], word[maxwl]; 54 Trie trie; 55 56 int main() { 57 int kase = 1; 58 while(scanf("%s%d", text, &S) == 2) { 59 trie.clear(); 60 for(int i = 1; i <= S; i++) { 61 scanf("%s", word); 62 len[i] = strlen(word); 63 trie.insert(word, i); 64 } 65 memset(d, 0, sizeof(d)); 66 int L = strlen(text); 67 d[L] = 1; 68 for(int i = L-1; i >= 0; i--) { 69 vector<int> p; 70 trie.find_prefixes(text+i, L-i, p); 71 for(int j = 0; j < p.size(); j++) 72 d[i] = (d[i] + d[i+len[p[j]]]) % MOD; 73 } 74 printf("Case %d: %d\n", kase++, d[0]); 75 } 76 return 0; 77 }
以上是关于uvaliva3942(trie树)的主要内容,如果未能解决你的问题,请参考以下文章
UVALive - 3942 Remember the Word[Trie DP]
(trie)UVALive - 3942 Remember the Word
UVALive - 3942 Remember the Word (Trie + DP)