1. 程式人生 > >UVALive - 3942 Remember the Word (Trie + DP)

UVALive - 3942 Remember the Word (Trie + DP)

The trie pri turn print %d txt esp 註意

題意:

給定一篇長度為L的小寫字母文章, 然後給定n個字母, 問有多少種方法用這些字母組成文章。

思路:

用dp[i]來表達[i , L]的方法數, 那麽dp[i] 就可以從dp[len(x) + i]轉移過來, 註意dp[L+1]要初始化為1.

遞推寫法

#include <bits/stdc++.h>
using namespace std;
const int maxN = 3e5 + 7;
const int mod =  20071027;
char in[maxN];
int n;
struct Trie {
    int ch[maxN][26];
    int val[maxN];
    
int sz; void Init(){sz = 1; memset(ch[0], 0, sizeof(ch[0])); memset(val, 0, sizeof(val));} int idx(char c) {return c - a;} void Insert(char *s){ int u = 0, n = strlen(s); for(int i = 0; i < n; 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] = n; } }tree; long long dp[maxN]; int main(){ // freopen("1.txt","r", stdin); int kase = 1; while(~scanf("%s", in)){ tree.Init(); memset(dp ,
0 , sizeof(dp)); scanf("%d", &n); char word[100]; for(int i = 0; i < n; i++){ scanf("%s", word); tree.Insert(word); } int len = strlen(in); dp[len] = 1; for(int pos = len ; pos >= 0; pos--){ int u = 0; for(int i = pos, wordLen = 1; i < len; i++, wordLen++){ int c = tree.idx(in[i]); if(tree.ch[u][c] == 0) break; u = tree.ch[u][c]; if(tree.val[u] != 0){ dp[pos] += dp[pos + wordLen]; dp[pos] %= mod; } } } printf("Case %d: %lld\n", kase++, dp[0]); } return 0; }

記憶化搜索

#include <bits/stdc++.h>
using namespace std;
const int maxN = 2e6 + 7;
const int mod =  20071027;
char in[maxN];
int n;
struct Trie {
    int ch[maxN][26];
    int val[maxN];
    int sz;
    void Init(){
        sz = 1;
        memset(ch[0], 0, sizeof(ch[0]));
        memset(val, 0, sizeof(val));
    }
    int idx(char c) {return c - a;}
    void Insert(char *s){
        int u = 0, n = strlen(s);
        for(int i = 0; i < n; 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] = n;
    }

}tree;

long long dp[maxN];
int dfs(int pos){
    int temp = pos;
    if(dp[pos] > 0) return dp[pos];
    int ret = 0;
    int adr = 0;
    while(tree.ch[adr][in[pos] - a]){
        adr = tree.ch[adr][in[pos] - a];
        if(tree.val[adr] != 0){
            ret = (ret + dfs(pos + 1)) % mod;
        }
        pos ++;

    }
    dp[temp] = ret;
    return ret;
}

int main(){
    freopen("1.txt","r", stdin);
    int ncase = 1;
    while(~scanf("%s", in)){
        tree.Init();
        scanf("%d", &n);
        char word[100];
        for(int i = 0; i < n; i++){
            scanf("%s", word);
            tree.Insert(word);
        }

        int l = strlen(in);
        for(int i = 0;i <= l; i ++)dp[i] = 0;
        dp[l] = 1;
        printf("Case %d: %d\n",ncase ++ , dfs(0));
    }

    return 0;
}

UVALive - 3942 Remember the Word (Trie + DP)