【题意】给出一个有S个不同单词组成的字典和一个字符串。把这个字符串分解成若干个单词的连接,有多少种方法?

【解题方法】令dp[i]表示以字符i结束的字符串的分解方案数,即dp[i+j] = sum(dp[i]) (j为一个单词的长度),初始化dp[0] = 1;把所有单词组成Trie,然后试着在Trie中查找单词即可。

【代码君】

//
//Created by just_sort 2016/10/12
//Copyright (c) 2016 just_sort.All Rights Reserved
//

#include <set>
#include <map>
#include <queue>
#include <stack>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
const int maxn = 444444;
const int maxm = 26;
const int mod =  20071027;
int dp[333333];
char s[333333];
struct Trie{
    int ch[maxn][maxm],val[maxn],root,sz;
    int newnode(){
        val[sz] = 0;
        memset(ch[sz],0,sizeof(ch[sz]));
        return sz++;
    }
    void init(){
        sz = 0;
        root = newnode();
    }
    void insert(char *s,int v){
        int len = strlen(s);
        int u = root;
        for(int i = 0; i < len; i++){
            int now = s[i] - 'a';
            if(!ch[u][now]){
                ch[u][now] = newnode();
            }
            u = ch[u][now];
        }
        val[u] = v;
    }
//    int find(char *s){
//        int len = strlen(s);
//        int u = root;
//        for(int i = 0; i < len; i++){
//            int now = s[i] - 'a';
//            if(!ch[u][now]) return 0;
//            u = ch[u][now];
//        }
//        return val[u];
//    }
}trie;

int main()
{
    int ks = 1, n;
    while(scanf("%s",s+1)!=EOF)
    {
        trie.init();
        scanf("%d",&n);
        for(int i = 1; i <= n; i++){
            char op[110];
            scanf("%s",op);
            trie.insert(op, 1);
        }
        int len = strlen(s+1);
        memset(dp, 0, sizeof(dp));
        dp[0] = 1; s[0] = '$';
        for(int i = 0; s[i]; i++)
        {
            int u = 0;
            for(int j = 1; j <= len; j++){
                int now = s[i+j] - 'a';
                u = trie.ch[u][now];
                if(!u) break;
                else if(trie.val[u] == 1){
                    dp[i+j] = (dp[i+j] + dp[i]) % mod;
                }
            }
        }
        printf("Case %d: %d\n",ks++,dp[len]);
    }
    return 0;
}