题意:给出一个由S个不同单词组成的字典和一个长字符串。把这个字符串分解成若干个单词的连接(单词可重复使用),有多少种方法?
解题思路:用Trie存入字典,设dp[i]为从字符i开始的字符串的分解方案数,
则有dp[i] = sum{dp[i+len(x)] | 单词x为S[i...L]的前缀}。
139MS
1 /* 2 *Author: Zhaofa Fang 3 *Created time: 2013-04-02-21.55 4 *Language: C++ 5 */ 6 #include <cstdio> 7 #include <cstdlib> 8 #include <sstream> 9 #include <iostream> 10 #include <cmath> 11 #include <cstring> 12 #include <algorithm> 13 #include <string> 14 #include <utility> 15 #include <vector> 16 #include <queue> 17 #include <stack> 18 #include <map> 19 #include <set> 20 using namespace std; 21 22 typedef long long ll; 23 #define DEBUG(x) cout<< #x << ':' << x << endl 24 #define REP(i,n) for(int i=0;i < (n);i++) 25 #define REPD(i,n) for(int i=(n-1);i >= 0;i--) 26 #define FOR(i,s,t) for(int i = (s);i <= (t);i++) 27 #define FORD(i,s,t) for(int i = (s);i >= (t);i--) 28 #define PII pair<int,int> 29 #define PB push_back 30 #define MP make_pair 31 #define ft first 32 #define sd second 33 #define lowbit(x) (x&(-x)) 34 #define INF (1<<30) 35 36 const int maxnode = 400111; 37 const int sigma_size = 26; 38 const int mod = 20071027; 39 int dp[300111]; 40 char str[300111]; 41 int ch[maxnode][sigma_size]; 42 struct Trie{ 43 44 bool val[maxnode]; 45 int sz; 46 Trie(){sz = 1;memset(ch[0],0,sizeof(ch[0]));} 47 int idx(char c){return c-'a';} 48 49 void insert(char *S){ 50 int u = 0, len = strlen(S); 51 REP(i,len){ 52 int c = idx(S[i]); 53 if(!ch[u][c]){ 54 memset(ch[sz],0,sizeof(ch[sz])); 55 val[sz] = 0; 56 ch[u][c] = sz++; 57 } 58 u = ch[u][c]; 59 } 60 val[u] = 1; 61 } 62 63 int find(char *S,int pos){ 64 int ans = 0; 65 int u = 0,len = strlen(S); 66 for(int i=pos;i<len&&i<pos+101;i++){ 67 int c = idx(S[i]); 68 if(!ch[u][c])return ans; 69 u = ch[u][c]; 70 if(val[u])ans = (ans+dp[i+1])%mod; 71 } 72 return ans; 73 } 74 }; 75 int main(){ 76 //freopen("in","r",stdin); 77 //freopen("out","w",stdout); 78 int cas = 0; 79 while(~scanf("%s",str)){ 80 int n; 81 scanf("%d",&n); 82 char str1[110]; 83 Trie pp; 84 REP(i,n){ 85 scanf("%s",str1); 86 pp.insert(str1); 87 } 88 int len = strlen(str); 89 dp[len] = 1; 90 REPD(i,len)dp[i] = pp.find(str,i); 91 printf("Case %d: %d\n",++cas,dp[0]); 92 } 93 return 0; 94 }