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\n", ++kase, dp[0]); 56 } 57 return 0; 58 }