洛谷.2292.[HNOI2004]L语言(Trie DP)

本文介绍了一种结合Trie树和动态规划的方法来解决字符串中的单词拆分问题。通过构建Trie树来存储字典中的所有单词,并利用动态规划算法检查输入字符串是否能被字典中的单词完全覆盖。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接

/*
简单的DP,查找是否有字典中的单词时在Trie树上做 
要注意在最初Match(0)一遍后,i还是要从0开始匹配,因为如果有长度为1的单词,Match(i+1)不会从1更新 

1M=1024K=1024*1024B
*/
#include<cstdio>
#include<cstring>
const int N=1025*1025,M=220,S=28;

int n,m,tot,son[M][S],qu[M],qid[M];
bool dp[N],vis[M];
char s[N];

void Insert()
{
    int l=strlen(s),u=0,id;
    for(int i=0;i<l;++i)
    {
        id=s[i]-'a';
        if(!son[u][id]) son[u][id]=++tot;
        u=son[u][id];
    }
    vis[u]=1;
}
bool Match(int p)
{
    int id,id2,u,h=0,t=1;
    qu[0]=0,qid[0]=p;
    while(h<t)
    {
        u=qu[h], id=s[qid[h]]-'a', id2=qid[h++];
//      printf(" %d:\t  u:%d id:%c i:%d\n",p,u,id+'a',id2);
//      if(dp[id2]) continue;//不要有这个!dp与当前的u和id都有关 
        if(!son[u][id]) continue;
        u=son[u][id];
        if(vis[u]) dp[id2]=1;
//      printf("dp:%d\n",dp[id2]);
        qu[t]=u, qid[t++]=id2+1;
    }
}

int main()
{
//  freopen("language.in","r",stdin);
//  freopen("language.out","w",stdout);

    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;++i)
        scanf("%s",s),Insert();
    for(int i=1;i<=m;++i)
    {
        scanf("%s",s);
        int l=strlen(s);
        memset(dp,0,sizeof dp);
//      dp[0]=1;
        int ans=0;
        Match(0);
        for(int j=0;j<l;++j)
            if(dp[j]) ans=j+1, Match(j+1);//这是j+1...注意条件也不要设成j<l-1 
        printf("%d\n",ans);
    }

    return 0;
}

转载于:https://www.cnblogs.com/SovietPower/p/8435063.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值