LA3942 字典树+ dp

这题dp思想很简单,主要用到了字典树记录单词是否出现,即字典的功能。不过刚开始做数据结构的题,还没有联想到和dp结合。这是一次思维的突破吧。

还有就是计算字典树节点的个数,得用字符串的长度*个数得来。

代码:

#include<iostream>
#include<cstdio>
#include<vector>
#include<string>
#include<queue>
#include<cmath>
#include<algorithm>
#include<cstring>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define maxn 300005
#define maxm 105
#define INF 0xfffffff
#define mem(a,b) memset(a,b,sizeof(a))
#define FOR(i,s,t) for(int i=s;i<=t;i++)
#define ull unsigned long long
#define ll long long
#define MOD 20071027
using namespace std;
char s[maxn],S[4005][105];
int dp[maxn];
struct trie
{
    int ch[26];
    int val;
    trie(){memset(ch,0,sizeof(ch));val=0;}
}T[400005];
int num=0;
void build(char *s)
{
    int l=strlen(s);
    int p=0;
    for(int i=0;i<l;i++)
    {
        int c=s[i]-'a';
        if(T[p].ch[c]==0)
        {
            T[p].ch[c]=++num;
        }
        p=T[p].ch[c];
    }
    T[p].val=1;
}
bool search(char *s,int l)
{
    int p=0;
    for(int i=0;i<l;i++)
    {
        int c=s[i]-'a';
        if(T[p].ch[c]==0)
        {
            return false;
        }
        p=T[p].ch[c];
    }
    if(T[p].val==1)
    return true;
    else
    return false;
}
void init(int n)
{
    num=0;
    memset(dp,0,sizeof(dp));
    for(int i=0;i<400005;i++)
    {
        T[i].val=0;
        memset(T[i].ch,0,sizeof(T[i]));
    }
}
int main()
{
    int tt=1;
    while(scanf("%s",s)!=EOF)
    {
        int n;
        scanf("%d",&n);init(n);
        for(int i=0;i<n;i++)
        {
            scanf("%s",S[i]);
            build(S[i]);
        }
        int l=strlen(s);
        dp[l]=1;
        for(int i=l-1;i>=0;i--)
        {
            for(int j=1;j<=100;j++)
            {
                if(i+j>l) break;
                if(search(s+i,j))
                {
                    dp[i]=(dp[i]+dp[i+j])%MOD;
                }
            }
        }
        printf("Case %d: %d\n",tt++,dp[0]);
    }
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值