题解 UVA1401 【Remember the Word】

Solution

第一次写Trie,写篇题解纪念一下......

令d(i)表示从字符i开始的字符串(即后缀 S[i...L-1])的分解方案数,则d(i)=sum{d(i+len(x)) | 单词x是 S[i...L-1]的前缀}。

显然,关键点就在判断前缀上。可以把所有的单词组织成Trie,然后试着在Trie中查找S[i...L-1],每找到一个单词节点,就状态转移一次....

#include<cstdio>
#include<cstring>
const int mod=20071027;
const int maxL=300000;
int L,S,d[maxL+5],kase;
char str[maxL+5],tmp[105];
const int maxnode=4000*105;//注意开大一点
const int sigma_size=26;
struct Trie
{
    int ch[maxnode][sigma_size];
    bool val[maxnode];
    int sz;
    Trie() { sz=1; }
    inline void clear()
    {
        sz=1;
        memset(ch,0,sizeof(ch));
        memset(val,0,sizeof(val));//一次性赋值
    }
    inline void insert(char *s)
    {
        int u=0,n=strlen(s);
        for(int i=0;i<n;i++)
        {
            int c=s[i]-'a';
            if(!ch[u][c])
                ch[u][c]=sz++;//申请新节点
            u=ch[u][c];
        }
        val[u]=1;
    }
}trie;
int main()
{
#ifdef local
    freopen("pro.in","r",stdin);
#endif
    while(scanf("%s",str)==1)
    {
        L=strlen(str);
        scanf("%d",&S);
        memset(d,0,sizeof(d));
        trie.clear();
        for(int i=0;i<S;i++)
        {
            scanf("%s",tmp);
            trie.insert(tmp);
        }
        d[L]=1;//边界
        for(int i=L-1;i>=0;i--)
            for(int j=0,u=0;i+j<L&&trie.ch[u][str[i+j]-'a'];j++)
            {
                u=trie.ch[u][str[i+j]-'a'];
                if(trie.val[u]) d[i]=(d[i]+d[i+j+1])%mod;
                //状态转移
            }
        printf("Case %d: %d\n",++kase,d[0]);
    }
    return 0;
}

转载于:https://www.cnblogs.com/happyZYM/p/11380110.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值