ACM
题目地址:
UVALive 3942 - Remember the Word
题意:
给一些单词,然后给一个长的单词,问有几种方法能组成这个大单词,单词可以重复用。
分析:
DP[i]=sum{DP[j} (i<j<len)
,从后往前求。
本来用数组Trie写得爽爽的,1A了。
发现2s多,不能忍!
然后用指针Trie写了一遍,各种出错,整个人都不好了...
研究了一遍别人代码,发现快的都是没写成一个struct的,无语。
代码:
(数组Trie)
/* * Author: illuz <iilluzen[at]gmail.com> * File: UVALive3942.cpp * Create Date: 2014-09-23 15:43:26 * Descripton: trie */ #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define repf(i,a,b) for(int i=(a);i<=(b);i++) typedef long long ll; const int N = 300010; const int MAXNODE = 400010; const int MAXSON = 26; const int MOD = 20071027; char st[N], wd[110]; int cas, n; int d[N]; // array index struct ATrie { int ch[MAXNODE][MAXSON]; int val[MAXNODE]; int sz; // num of nodes ATrie() { sz = 1; memset(ch[0], 0, sizeof(ch[0])); } void init() { sz = 1; memset(ch[0], 0, sizeof(ch[0])); } inline int idx(char c) { return c - 'a'; } void insert(char *s, int v = 1) { int u = 0, len = strlen(s); repf (i, 0, len - 1) { int c = idx(s[i]); if (!ch[u][c]) { memset(ch[sz], 0, sizeof(ch[sz])); val[sz] = 0; ch[u][c] = sz++; } u = ch[u][c]; } val[u] = v; } // if s in trie return the value, else return 0 int find(char *s, int pos) { int u = 0, len = strlen(s), cnt = 0; repf (i, 0, len) { int c = idx(s[i]); if (val[u]) cnt = (cnt + d[pos + i]) % MOD; if (ch[u][c]) u = ch[u][c]; else return cnt; } } } trie; int main() { // ios_base::sync_with_stdio(0); cas = 1; while (~scanf("%s", st)) { trie.init(); scanf("%d", &n); repf (i, 0, n - 1) { scanf("%s", wd); trie.insert(wd); } int len = strlen(st); d[len] = 1; for (int i = len - 1; i >= 0; i--) { d[i] = trie.find(st + i, i); } printf("Case %d: %d\n", cas++, d[0]); } }
(指针Trie)
/* * Author: illuz <iilluzen[at]gmail.com> * File: UVALive3942_pointer_trie.cpp * Create Date: 2014-09-23 16:24:32 * Descripton: pointer trie */ #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define repf(i,a,b) for(int i=(a);i<=(b);i++) typedef long long ll; const int N = 300010; const int MAXSON = 26; const int MOD = 20071027; char st[N], wd[110]; int cas, n; int d[N]; // pointer trie struct Node { int val; Node *next[MAXSON]; }; struct PTrie { Node *root; PTrie() { root = newNode(); } void init() { del(root); root = newNode(); } inline int idx(char c) { return c - 'a'; } Node *newNode() { Node *u = new Node; repf (i, 0, MAXSON - 1) { u->next[i] = NULL; } u->val = 0; return u; } void insert(char *s, int v = 1) { Node *u = root; int len = strlen(s); repf (i, 0, len - 1) { int c = idx(s[i]); if (u->next[c] == NULL) { u->next[c] = newNode(); } u = u->next[c]; } u->val = v; } int find(char *s, int pos) { Node*u = root; int len = strlen(s), cnt = 0; repf (i, 0, len) { // remember to len if (u->val) cnt = (cnt + d[pos + i]) % MOD; if (i == len) // prevent to voer the string return cnt; int c = idx(s[i]); if (u->next[c] == NULL) return cnt; u = u->next[c]; } } void del(Node *rt) { if (rt == NULL) return; else { repf (i, 0, MAXSON - 1) if (rt->next[i] != NULL) del(rt->next[i]); } delete rt; } } trie; int main() { // ios_base::sync_with_stdio(0); cas = 1; while (~scanf("%s", st)) { scanf("%d", &n); repf (i, 0, n - 1) { scanf("%s", wd); trie.insert(wd); } int len = strlen(st); d[len] = 1; int i = len - 1; while (i >= 0) { d[i] = trie.find(st + i, i); i--; } printf("Case %d: %d\n", cas++, d[0]); trie.init(); } }