UVALive - 3942 (字典树)
递推:$d(i) $表示从第$i$个字符开始到末尾的字符串(即后缀S[i...n])的分解方案数,则$d(i) = \sum {d(i + len(x))} $,其中字符串$x$代表S[i...n]的前缀,且x可以和某个单词匹配。判断后缀串S[i...n]能和哪些单词匹配,使用字典树来实现O(100)复杂度判断。
AC代码
#include <stdio.h> #include <string.h> const int MOD = 20071027; const int maxnode = 4000 * 100 + 5; const int sigma_size = 26; const int maxn = 300000 + 5; char S[maxn], sb[100 + 5]; int d[maxn]; 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(char *s) { int u = 0, n = strlen(s); for(int i = 0; i < n; i++) { int c = idx(s[i]); if(!ch[u][c]) { val[sz] = 0; memset(ch[sz], 0, sizeof(ch[sz])); ch[u][c] = sz++; } u = ch[u][c]; } val[u] = n; } void query_prefix(char *s, int i, int *d) { int u = 0; for(int j = 0; s[j] != '\0'; j++) { int c = idx(s[j]); if(!ch[u][c]) break; u = ch[u][c]; if(val[u]) { d[i] = (d[i] + d[i + val[u]]) % MOD; } } } }; Trie tree; int main() { int m, kase = 1; while(scanf("%s", S) == 1) { tree.clear(); scanf("%d", &m); for(int i = 0; i < m; i++) { scanf("%s", sb); tree.insert(sb); } int n = strlen(S); d[n] = 1; for(int i = n-1; i >= 0; i--) { d[i] = 0; tree.query_prefix(S+i, i, d); } printf("Case %d: %d\n", kase++, d[0]); } return 0; }
如有不当之处欢迎指出!