• LA 3942


    https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1943

    题目大意:

      给定一个字符串和给定一个单词集合。问从给定单词集合中选取单词,有多少种选取方法刚好拼接成字符串。

    例如:

    abcd

    4

    a

    b

    cd

    ab

    有两种

    a-b-cd

    ab-cd

    这两种情况

    解题思路:

      因为给定的字符串的长度是3*10^5所以暴力就不能解决问题了。

    dp[j + 1] = dp[j + 1] + dp[i];dp[j + 1]表示从S[0~j]有多少中组成方法 ,用公式的条件是S[i~j]是单词集合里的元素

    有了上面的dp,时间减少了,但是每次查找单词如果枚举每个单词,则时间复杂度3*10^5*4*10^3*10^2。我们用字典树

    存储所有单词。每次查找单词时间最坏是O(10^2)。

      所以总时间复杂度是O(n*10^2)。

      参开资料《算法入门经典训练之南》刘汝佳 P209

    AC代码:

     1 #include<cstdio>
     2 #include<cstring>
     3 
     4 #define STR 300000 + 10//模板串的长度
     5 #define SIZE 400000 //字典树的节点数
     6 #define LETTER 26 //字符个数
     7 #define S 100+10//单词的长度
     8 #define MOD 20071027
     9 
    10 int size, trie[SIZE][LETTER];//size字典的节点数 trie字典树的节点
    11 bool val[SIZE];//记录字典树的节点是否为单词
    12 char strp[STR];//模板单词
    13 int dp[STR];//dp[i]表示从0~i有多少种组成模板单词
    14 
    15 void init(int x){//初始化节点
    16     val[x] = 0;
    17     memset(trie[x], 0, sizeof(trie[x]));
    18 }
    19 
    20 int idx(char c){
    21     return c - 'a';
    22 }
    23 
    24 void insert(char str[]){
    25     int u = 0;
    26     for(int i = 0; str[i]; ++i){
    27         int num = idx(str[i]);
    28         if(!trie[u][num]){//儿子为空 
    29             init(size);//扩充节点
    30             trie[u][num] = size++;
    31         }
    32         u = trie[u][num];//指向下一个节点
    33     }
    34     val[u] = true;//当前节点是一个单词的末尾
    35 }
    36 
    37 void dynamic(int cs){
    38     memset(dp, 0, sizeof(dp));
    39     dp[0] = 1;
    40     int i;
    41     for(i = 0; strp[i]; ++i){
    42         int u = 0;
    43         for(int j = i; strp[j]; ++j){
    44             int num = idx(strp[j]);
    45             if(!trie[u][num]){
    46                 break;
    47             }
    48             u = trie[u][num];
    49             if(val[u]){
    50                 dp[j + 1] = (dp[j + 1] + dp[i]) % MOD;//dp公式
    51             }
    52         }
    53     }
    54     printf("Case %d: %d
    ", cs, dp[i]);
    55 }
    56 
    57 int main(){
    58     int s;
    59     char str[S];
    60     for(int cs = 1; ~scanf("%s", strp); ++cs){
    61 
    62         init(0);//初始化节字典树
    63         size = 1;
    64 
    65         scanf("%d", &s);
    66         while(s--){
    67             scanf("%s", str);
    68             insert(str);
    69         }
    70         dynamic(cs);
    71     }
    72     return 0;
    73 }
  • 相关阅读:
    Html页面渲染
    神思SS628(100)型第二代身份证验证阅读机B/S二次开发
    ASP.NET面试问题一天5问(四)
    ASP.NET面试问题一天5问(三)
    asp.net 面试问题一天5问(二)
    ASP.NET面试问题一天5问(一)
    ASP.NET MVC 3 第一天笔记
    2019 END → 2020 BEGIN
    vs中自己常用的快捷方式
    Dapper使用入门Demo
  • 原文地址:https://www.cnblogs.com/xuqiulin/p/4034143.html
Copyright © 2020-2023  润新知