zoukankan      html  css  js  c++  java
  • LA3942字典树+递推

    题意:
         给你一个字典,最多4000个单词,每个单词长度最多是100,然后给你一个串,问你这个子串可以被那些单词组合的组合数,比如字典里有4个单词a b ab cd,然后给你一个串abcd则abcd = a+b+cd,ab+cd一共两种组合。输出组合数对20071027取余(白书上写错了写的是20071207)


    思路:
           我们可以找到一个递推公式,d[i] = sum(i + len[x]),解释一下这个,d[i]表示的是以i个位置为开头的字符串的组合个数,就是[i,i+1,i+2..len-1],而x则是以i开头的那个串的前缀,这样就不难理解了吧,整体意思就是如果defg = 5,那么只要存在bc,就可以得到以a开头的abcdefg可以加上5了,然后就是优化时间,因为直接暴力写的话30000*4000*判断前缀匹配,时间复杂度接受不了,既然是前缀,我们可以想到字典树,我们可以把所有的4000个单词都放到字典里,然后在匹配的时候如果碰到单词末尾节点,直接就是找到满足条件,更新左右值,就行了,具体看代码,很容易理解。
    PS不要把30000的那个字符串拆开放到字典树里,一开始我就是这么想的,结果还没敲完意识到这样内存会很大,很可能会爆内存,还有就是别忽视strlen这个函数的时间复杂度,TLE了一次。
          




    #include<stdio.h>
    #include<string.h>
    #include<stdlib.h>


    #define N 300000 + 10
    #define MOD 20071027


    typedef struct Tree
    {
        Tree *next[26];
        int mk;
    }Tree;


    Tree root;
    char Str[N];
    long long dp[N];


    void BuidTree(char *str)
    {
        int len = strlen(str);
        Tree *p = &root ,*q;
        for(int i = 0 ;i < len ;i ++)
        {
            int id = str[i] - 'a';
            if(p -> next[id] == NULL)
            {
                q = (Tree *)malloc(sizeof(root));
                q -> mk = 0;
                for(int j = 0 ;j < 26 ;j ++)
                q -> next[j] = NULL;
                p -> next[id] = q;
                p = p -> next[id];
            }
            else
            p = p -> next[id];
        }
        p -> mk = 1;
    }


    void Query(char *str ,int ii ,int len)
    {
        dp[ii] = 0;
        Tree *p = &root;
        for(int i = ii ;i < len ;i ++)
        {
            int id = str[i] - 'a';
            p = p -> next[id];
            if(p == NULL) break;
            if(p -> mk) dp[ii] = (dp[ii] + dp[i+1]) % MOD;
        }
        return ;
    }


    int main ()
    {
        int cas = 1 ,i ,n;
        char tmp[105];
        while(~scanf("%s" ,Str))
        {
            scanf("%d" ,&n);
            for(i = 0 ;i < 26 ;i ++)
            root.next[i] = NULL;
            for(i = 1 ;i <= n ;i ++)
            {
                scanf("%s" ,tmp);
                BuidTree(tmp);
            }
            int len = strlen(Str);
            dp[len] = 1;
            for(i = len - 1 ;i >= 0 ;i --)
            {
                Query(Str ,i ,len);//把len直接传下去,别在里面从求,会超时。
            }
            printf("Case %d: %lld " ,cas ++ ,dp[0]);
        }
    }









  • 相关阅读:
    算法复杂度(Algorithmic Complexity)
    Javascript引用指针
    树(Trees)
    什么是数据挖掘(What is Data Mining?)
    Javascript的声明
    Javascript继承(下)——干嘛要继承
    Linux 中使用 OpenCV
    Java集合类(Java Collections classes)
    哈希查找(Hashing)
    Javascript继承(上)——对象构建
  • 原文地址:https://www.cnblogs.com/csnd/p/12062539.html
Copyright © 2011-2022 走看看