注意到单词的长度最长100,其实最糟糕复杂度应该能到O(300005*100),需要注意的是在字典树上匹配单词时,一旦不匹配,则后面的就不会匹配,需要break出来(这个害我TLE查了半天,日!),还有,要注意strlen的时候,那个api的复杂度貌似是O(n)的,题目中提到输入数据的不同的test case之间有一个blank line,我理解成输出不同case之间要回车,OJ居然没判成PE,而是判成WA,这两天题写的真蛋疼(吐槽下)。
#include <cstdio> #include <cstring> #include <vector> #include <stack> #include <iostream> using namespace std; const int MAXN = 300005; const int M = 20071027; typedef long long int64; char ch[MAXN]; int64 dp[MAXN]; int id[4005 * 105][26], cnt; bool flag[4005 * 105]; class DicNode { public: bool flag; DicNode *sons[26]; DicNode() { flag = false; memset(sons, NULL, sizeof(sons)); } }; class DicTree2 { public: DicTree2() { cnt = 1; memset(id, -1, sizeof(id)); memset(flag, false, sizeof(flag)); } ~DicTree2() { } void insert(const char *s) { int len = strlen(s); int node = 0; for (int i = 0; i < len; i++) { if (id[node][s[i] - 'a'] == -1) { id[node][s[i] - 'a'] = cnt++; } node = id[node][s[i] - 'a']; if (i == len - 1) { flag[node] = true; } } } bool query(const char *s) { int len = strlen(s); int node = 0; for (int i = 0; i < len; i++) { if (id[node][s[i] - 'a'] == -1) { return false; } node = id[node][s[i] - 'a']; } return flag[node]; } int64 f(int b, int len) { if (dp[b] != -1) return dp[b]; dp[b] = 0; if (b == len) return dp[b] = 1; int node = 0; for (int i = b; i < len; i++) { if (id[node][ch[i] - 'a'] != -1) { node = id[node][ch[i] - 'a']; if (flag[node]) dp[b] = (dp[b] + f(i + 1, len)) % M; } else { break; } } return dp[b]; } }; class DicTree { public: DicNode *root; DicTree() { root = new DicNode(); } ~DicTree() { if (NULL != root) { free(root); } } void free(DicNode *node) { for (int i = 0; i < 26; i++) { if (node->sons[i] != NULL) { free(node->sons[i]); } } delete node; } void insert(const char *s) { int len = strlen(s); DicNode *node = root; for (int i = 0; i < len; i++) { if (node->sons[s[i] - 'a'] == NULL) { node->sons[s[i] - 'a'] = new DicNode(); } node = node->sons[s[i] - 'a']; if (i == len - 1) { node->flag = true; } } } bool query(const char *s) { int len = strlen(s); DicNode *node = root; for (int i = 0; i < len; i++) { if (node->sons[s[i] - 'a'] == NULL) { return false; } node = node->sons[s[i] - 'a']; } return node->flag; } int64 f(int b, int len) { if (dp[b] != -1) return dp[b]; dp[b] = 0; if (b == len) return dp[b] = 1; DicNode *node = root; for (int i = b; i < len; i++) { if (node->sons[ch[i] - 'a'] != NULL) { node = node->sons[ch[i] - 'a']; if (node->flag) dp[b] = (dp[b] + f(i + 1, len)) % M; } else { break; } } return dp[b]; } }; int main() { int c = 0; while (scanf("%s", ch) != EOF) { int s; scanf("%d", &s); DicTree dic; for (int i = 0; i < s; i++) { char str[105]; scanf("%s", str); dic.insert(str); } memset(dp, -1, sizeof(dp)); printf("Case %d: %lld ", ++c, dic.f(0, strlen(ch))); } }