UVALive 3942 (LA 3492) Remember the Word Trie树 + 记忆化搜索

来源:互联网 发布:网络信息安全法 编辑:程序博客网 时间:2024/05/17 04:52

题目大意:

白书例题

给出由S个不同单词组成的字典和一个长字符串. 把这个字符串分解成若干个单词的连接, 单词可以重复使用, 问有多少种分解方法

单词个数1 <= S <=4000, 每个单词长度不超过100, 给出的长字符串长度不超过300000


大致思路:

首先将S个单词插入Trie树, 然后利用递推的思想记忆化搜索即可


代码如下:

Result  :  Accepted     Memory  :  ? KB     Time  :  79 ms

/* * Author: Gatevin * Created Time:  2015/2/11 13:44:36 * File Name: Mononobe_Mitsuki.cpp */#include<iostream>#include<sstream>#include<fstream>#include<vector>#include<list>#include<deque>#include<queue>#include<stack>#include<map>#include<set>#include<bitset>#include<algorithm>#include<cstdio>#include<cstdlib>#include<cstring>#include<cctype>#include<cmath>#include<ctime>#include<iomanip>using namespace std;const double eps(1e-8);typedef long long lint;/* * 白书例题, 先建立S个单词的Trie树然后在Trie树上递推记忆化搜索 */const int mod = 20071027;int dp[300010];struct Trie{    int next[400010][26];    bool end[400010];    int L, root;    int newnode()    {        for(int i = 0; i < 26; i++)            next[L][i] = -1;        end[L++] = 0;        return L - 1;    }    void init()    {        L = 0;        root = newnode();        return;    }    void insert(char *s)    {        int now = root;        for(; *s; s++)        {            if(next[now][*s - 'a'] == -1)                next[now][*s - 'a'] = newnode();            now = next[now][*s - 'a'];        }        end[now] = 1;        return;    }    int find(char *s, int num)//搜索后缀s位置开始的组成方法数    {        if(dp[num] != -1) return dp[num];//记忆化搜索        int tnum = num;        int ret = 0;        int now = root;        for(; *s; s++, num++)        {            if(next[now][*s - 'a'] == -1)                break;            now = next[now][*s - 'a'];            if(end[now])            {                if(*(s + 1) == '\0')                    ret = (ret + 1) % mod;                else                    ret = (ret + find(s + 1, num + 1)) % mod;            }        }        dp[tnum] = ret;        return ret;    }};Trie trie;char S[300010];char word[110];int main(){    int n;    int cas = 1;    while(scanf("%s", S) != EOF)    {        trie.init();        scanf("%d", &n);        while(n--)        {            scanf("%s", word);            trie.insert(word);//建立Trie树        }        int N = strlen(S);        for(int i = 0; i < N; i++) dp[i] = -1;        int ans = trie.find(S, 0);        printf("Case %d: %d\n", cas++, ans);    }    return 0;}


0 0
原创粉丝点击