• UVaLive 3942 Remember the Word (dp+字典树)



    Remember the Word

    DescriptionNeal is very curious about combinatorial problems, and now here comes a problem about words. Knowing that Ray has a photographic memory and this may not trouble him, Neal gives it to Jiejie. Since Jiejie can’t remember numbers clearly, he just uses sticks to help himself. Allowing for Jiejie’s only 20071027 sticks, he can only record the remainders of the numbers divided by total amount of sticks. The problem is as follows: a word needs to be divided into small pieces in such a way that each piece is from some given set of words. Given a word and the set of words, Jiejie should calculate the number of ways the given word can be divided, using the words in the set.

    Input

    The input file contains multiple test cases. For each test case: the first line contains the given word whose length is no more than 300 000. The second line contains an integer S, 1 ≤ S ≤ 4000. Each of the following S lines contains one word from the set. Each word will be at most 100 characters long. There will be no two identical words and all letters in the words will be lowercase. There is a blank line between consecutive test cases. You should proceed to the end of file.

    Output

    For each test case, output the number, as described above, from the task description modulo 20071027.

    Sample Input

    abcd

    4

    a

    b

    cd

    ab

    Sample Output

    Case 1: 2

    题意:给你一个长字符串,和一些短字符串,问你用短字符串拼成长字符串的方案数

    分析:很明显的dp题。定义状态dp[i]表示从i开始的字符串(后缀)的方案数,则转移方程就是dp[i]+=dp[i+len(x)],x是从i开始的字符串的前缀。

    接下来只要求出所有的前缀的长度就行了,枚举肯定会超时,考虑用字典树来做,将短的字符串按字典树建树,单词节点保存单词的长度和是否为单词的标记,每次去查找就行了。

     

    #include<bits/stdc++.h>
    using namespace std;
    
    const int MAXN = 26;
    const int MOD = 20071027;
    typedef struct Trie_Node
    {
        bool isWord;
        int len;
        struct Trie_Node *next[MAXN];
    }Trie;
    int l[110],tot;
    void Trie_insert(Trie *root,char *str)
    {
        Trie *p=root;
        int len=strlen(str);
        for(int i=0;i<len;i++)
        {
            int k=str[i]-'a';
            if(p->next[k]==NULL)
            {
                Trie *t=new Trie;
                for(int j=0;j<MAXN;j++)
                    t->next[j]=NULL;
                t->isWord=false;
                p->next[k]=t;
            }
            p=p->next[k];
        }
        p->isWord=true;
        p->len=len;
    }
    int Trie_search(Trie *root,char *str)
    {
        Trie *p=root;
        int len=strlen(str);
        for(int i=0;i<len;i++)
        {
            int k=str[i]-'a';
            if(p->next[k]==NULL) return tot;
            if(p->next[k]->isWord)
            {
                tot++;
                l[tot]=p->next[k]->len;
            }
            p=p->next[k];
        }
        return tot;
    }
    void Trie_del(Trie *root)
    {
        for(int i=0;i<MAXN;i++)
        {
            if(root->next[i]!=NULL)
                Trie_del(root->next[i]);
        }
        free(root);
    }
    
    char str[300010];
    char ss[110];
    int dp[3000010];
    
    int main()
    {
        int n;
        int iCase=0;
        while(scanf("%s",str)!=EOF)
        {
            iCase++;
            //cout<<str<<endl;
            scanf("%d",&n);
            memset(dp,0,sizeof(dp));
            Trie *root=new Trie;
            for(int i=0;i<MAXN;i++) root->next[i]=NULL;
            root->isWord=false;
            for(int i=1;i<=n;i++)
            {
                scanf("%s",ss);
                //cout<<ss<<endl;
                Trie_insert(root,ss);
            }
            int len=strlen(str);
            dp[len]=1;
            for(int i=len-1;i>=0;i--)
            {
                tot=0;
                memset(l,0,sizeof(l));
                //cout<<str+i<<endl;
                Trie_search(root,str+i);
                for(int j=1;j<=tot;j++)
                {
                    dp[i]+=dp[i+l[j]];
                    dp[i]%=MOD;
                }
            }
            printf("Case %d: %d
    ",iCase,dp[0]);
            Trie_del(root);
        }
        return 0;
    }

     

     

  • 相关阅读:
    idea破解
    metasploit常用命令(持續更新...)
    metasploit魔鬼训练营_XSS
    渗透测试流程
    中国电信猫后接路由器具体设置
    python首次尝试——hello world
    【阿圆总结】关于平时阅读的推荐
    【转载】curl 模拟 GETPOST 请求,curl查看响应头 以及 curl post 上传文件
    【转载】用实例给新手讲解RSA加密算法
    【翻译】Open ID Connect---OIDC 是什么东西?
  • 原文地址:https://www.cnblogs.com/wangdongkai/p/5738620.html
Copyright © 2020-2023  润新知