Ultraviolet A 1401 Remember the Word (Trie + DP), 1401 trie
Question: n (n <= 4000) words and a string (len <= 300000) are given. How many methods are there to splice the string into several words?
Idea: Trie: create a word as Trie, and then run "dp" and "dp [I]" to indicate the situation where the I-th letter in the string starts, then, for each State, you only need to find the word starting with the corresponding letter on the Trie tree, and then dp [I] = sum {dp [I + len (x)]} after status transfer, x is one of n words and can be queried using Trie.
Code:
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn = 300005;const int MOD = 20071027;int ch[maxn][26];int val[maxn];int sz;int idx(char c){return c-'a';}void insert(char* s){ int u = 0; int len = strlen(s); for(int i = 0; i < len; i++){ 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] = 1;}void init(){ sz = 1; memset(ch[0],0,sizeof(ch[0])); int m; scanf("%d",&m); char str[105]; while(m--){ scanf("%s",str); insert(str); }}int d[maxn];void find(int id, char* s){ d[id] = 0; int u = 0;// int len = strlen(s); for(int i = id; s[i]; i++){ int c = idx(s[i]); if(!ch[u][c]) return; u = ch[u][c]; if(val[u]) d[id] = (d[id]+d[i+1])%MOD; }}void solve(char* s){ int len = strlen(s); d[len] = 1; for(int i = len-1; i >= 0; i--){ find(i, s); } printf("%d\n",d[0]);}int main(){ int cas = 0; char s[maxn]; while(scanf("%s",s) != EOF){ init(); printf("Case %d: ",++cas); solve(s); } return 0;}
Note:
Do not use strlen () in the find function; otherwise, T_T is timed out .. Because the length of each call is obtained, and the time complexity is 0 (N * N );