Uva1401 Trie树 + 简单dp

题意 给你m个短字符串和一个长串,问你长串拆分成由短串组成的方法数。

思路 dp[i] 表示从i开始的长串后缀,可以用短串组成的方案数。dp[i] += dp[i+len(x)]  其中x是从i开始的长串后缀的前缀,这个前缀属于短串集合。初始条件dp[n] = 1.

           用短串建立Trie树,用长串后缀去在字典树上匹配,找到满足条件的短串,更新dp


注意:Trie树的maxnode要开够!!被这个点WA死了….


#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <assert.h>
using namespace std;
const int maxn = 310005;
const int MOD = 20071027;

const int maxlen = 110;
const int maxnum = 4000;
const int sigmasize = 26;
const int maxnode = maxnum*maxlen;
struct Trie{
    //内容存的是节点i,遇到j字符时,前往的节点号 
    int ch[maxnode][sigmasize];
    int val[maxnode];
    int sz;
    char ji;
    void init(char j = 'a'){
        ji = j;
        sz = 1;
        memset(ch[0],0,sizeof(ch[0]));
    }
    int idx(char c){
        return c - ji;
    }
    //插入一个单词 
    void insert(char* s,int v)
    {
        assert(v != 0);
        int now = 0;
        int n = strlen(s);
        for(int i=0;i<n;i++)
        {
            int c = idx(s[i]);
            if(!ch[now][c]){
                memset(ch[sz],0,sizeof(ch[sz]));
                val[sz] = 0;
                ch[now][c] = sz++;
            }
            now = ch[now][c];
        }
        val[now] = v;
    }
    //查找一个单词是否在字典树中,在返回val,不在,返回0 
    int find(char* str)
    {
        int now = 0;
        while(*str != 0)
        {
            int p = idx(*str);
            if(!ch[now][p])
            {
                return 0;
            }
            now = ch[now][p];
            str++;
        }
        return val[now];
    }
};
Trie tree;

int dp[maxn];
char str[maxn];
int n,m;
char tmp[maxlen];

int main()
{
    int i,j,t;
    t = 0;
    while(scanf("%s",str) != EOF)
    {
        t++;
        tree.init();
        n = strlen(str);
        scanf("%d",&m);
        
        for(i=0;i<m;i++)
        {
            scanf("%s",tmp);
            tree.insert(tmp,/*strlen(tmp)*/1);
        }
        memset(dp,0,sizeof(dp));
        dp[n] = 1;
        for(i=n-1;i>=0;i--)
        {
            int now = 0;
            for(j=0;i+j<n;j++)
            {
                int c = tree.idx(str[i+j]);
                if(!tree.ch[now][c]){
                    break;
                }
                now = tree.ch[now][c];
                if(tree.val[now] != 0)
                {
                    dp[i] = (dp[i] + dp[i+j+1]) % MOD;
                }
            } 
        }
        cout<<"Case "<<t<<": "<<dp[0]<<endl; 
    }
    return 0;
}
    原文作者:Trie树
    原文地址: https://blog.csdn.net/luke2834/article/details/44888753
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞