UVA - 1401 Remember the Word(trie+dp)

1、给一个串,在给一个单词集合,求用这个单词集合组成串,共有多少种组法。

例如:串 abcd, 单词集合 a, b, cd, ab

组合方式:2种:

a,b,cd

ab,cd

2、把单词集合建立字典树,然后从后向前dp,dp[i]=dp[i]+dp[i+len(x)]; 其中x为当前找到的前缀长度。

3、

#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;

#define MAX 26
#define MOD 20071027

int dp[300005];

struct Trie
{
    Trie *next[MAX];
    int v;   //根据需要变化,1代表无此单词,-1代表有此单词
};
Trie *root;

void createTrie(char *str)
{
    int len = strlen(str);
    Trie *p = root, *q;
    for(int i=0; i<len; ++i)
    {
        int id = str[i]-'a';
        if(p->next[id] == NULL)
        {
            // q = (Trie *)malloc(sizeof(Trie));
            q = new Trie;
            q->v = 1;    //初始v==1
            for(int j=0; j<MAX; ++j)
                q->next[j] = NULL;
            p->next[id] = q;
        }
        p = p->next[id];
    }
    p->v = -1;   //若为结尾,则将v改成-1表示
}
int findTrie(char *str,int mI,int len)
{
    int ret=0;
    //int len = strlen(str);//每次都计算,很浪费时间
    Trie *p = root;
    for(int i=mI; i<len; ++i)
    {
        int id = str[i]-'a';
        p = p->next[id];
        if(p == NULL)   //若为空集,表示不存以此为前缀的串
            return ret;
        if(p->v == -1){   //字符集中已有串是此串的前缀
            ret=(ret+dp[i+1])%MOD;
        }
    }
    return ret;
}
int deleteTrie(Trie* T)
{
    int i;
    if(T==NULL)
        return 0;
    for(i=0; i<MAX; i++)
    {
        if(T->next[i]!=NULL)
            deleteTrie(T->next[i]);
    }
    //free(T);
    delete(T);
    return 0;
}
int main()
{
    char str[300005];
    char str2[105];
    int i,S,len,mCase=0;
    while(~scanf("%s",str)){
        root=new Trie;
        for(i=0; i<MAX; i++)
            root->next[i]=NULL;
        memset(dp,0,sizeof(dp));
        len=strlen(str);
        scanf("%d",&S);
        while(S--){
            scanf("%s",str2);
            createTrie(str2);
        }

        dp[len]=1;
        for(i=len-1;i>=0;--i)
            dp[i]=findTrie(str,i,len);

        printf("Case %d: %d\n",++mCase,dp[0]);
        delete(root);
    }
    return 0;
}
View Code

 

转载于:https://www.cnblogs.com/bofengyu/p/4945896.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值