UvaLive3942(Trie + dp)

查了半天数组越界的RE,才发现自己把ch数组放结构体里是过大的……放全局就A了。

类似区间的dp比较显然,只是用trie树做了优化,使得可以在trie树里一边走一边往上加dp值,不必枚举以前的每个位置了,省去了很多不必要状态。复杂度就O(n*Trie)。

终于比刘汝佳的代码优雅了(弥天大雾)

 1 const int maxn = 3e5 + 5;
 2 const int maxnode = 4000 * 100 + 5;
 3 const int mod = 20071027;
 4 
 5 int ch[maxnode][26];
 6 
 7 struct Trie {
 8     int sz;
 9     bool IsWord[maxnode];
10 
11     Trie() { 
12         sz = 1;
13         init(ch[0], 0);
14     }
15 
16     void insert(char *t) {
17         int len = strlen(t), u = 0;
18         for (int i = 0; i < len; ++i) {
19             if (!ch[u][t[i] - 'a']) {
20                 init(ch[sz], 0);
21                 IsWord[sz] = false;
22                 ch[u][t[i] - 'a'] = sz++;
23             }
24             u = ch[u][t[i] - 'a'];
25         }
26         IsWord[u] = true;
27     }
28 
29     int find(int pos, char *str, int *dp) {
30         int ret = 0, u = 0;
31         for (int i = pos; str[i]; ++i) {
32             if (!ch[u][str[i] - 'a'])    return ret;
33             u = ch[u][str[i] - 'a'];
34             if (IsWord[u])    ret = ((ll)ret + dp[i + 1]) % mod;
35         }
36         return ret;
37     }
38 };
39 
40 char str[maxn], t[105];
41 int S, L, dp[maxn], kase;
42 
43 int main() {
44     while (~scanf("%s", str)) {
45         Trie T;
46         for (scanf("%d", &S); S; S--) {
47             scanf("%s", t);
48             T.insert(t);
49         }
50         L = strlen(str);
51         dp[L] = 1;
52         for (int i = L - 1; ~i; --i) {
53             dp[i] = T.find(i, str, dp);
54         }
55         printf("Case %d: %d
", ++kase, dp[0]);
56     }
57     return 0;
58 }
原文地址:https://www.cnblogs.com/AlphaWA/p/10573358.html