码迷,mamicode.com
首页 > 其他好文 > 详细

UVALive - 3942 Remember the Word (Trie + DP)

时间:2018-08-08 21:28:05      阅读:149      评论:0      收藏:0      [点我收藏+]

标签:col   转移   scan   val   pac   namespace   注意   temp   ali   

题意:

给定一篇长度为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)

标签:col   转移   scan   val   pac   namespace   注意   temp   ali   

原文地址:https://www.cnblogs.com/Jadon97/p/9445490.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!