zoukankan      html  css  js  c++  java
  • LA 3942 ——Trie (前缀树)、DP

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <algorithm>
     5 #include <vector>
     6 using namespace std;
     7 const int M = 20071027;
     8 const int maxn = 300000 + 10;
     9 const int maxnode = 400000+10;
    10 const int _size = 26;
    11 
    12 struct Trie {
    13     int ch[maxnode][_size];
    14     int val[maxnode];
    15     int sz;
    16     Trie() {
    17         sz = 1;
    18         memset(ch[0], 0, sizeof (ch[0]));
    19     }
    20     int idx(int c) {return c - 'a';}
    21     
    22     void insert(char *s, int v) {   //插入字符串s和权值v
    23         int u = 0, n = strlen(s);
    24         for(int i = 0; i < n; i++) {
    25             int c = idx(s[i]);
    26             if(!ch[u][c]) {
    27                 memset(ch[sz], 0, sizeof (ch[sz]));
    28                 val[sz] = 0;
    29                 ch[u][c] = sz++;
    30             }
    31             u = ch[u][c];
    32         }
    33         val[u] = v;
    34     }
    35     void find_prefixes(const char *s, int len, vector<int>& ans) { //寻找字符串s的前缀
    36         int u = 0;
    37         for(int i = 0; i < len; i++) {
    38             if(s[i] == '') break;
    39             int c = idx(s[i]);
    40             if(!ch[u][c]) break;
    41             u = ch[u][c];
    42             if(val[u] != 0) ans.push_back(val[u]);
    43         }
    44     }
    45     
    46     void clear() {
    47         sz = 1;
    48         memset(val, 0 , sizeof val);
    49         memset(ch[0], 0, sizeof (ch[0]));
    50     }
    51 };
    52 
    53 Trie T;
    54 char S[maxn], s[110];
    55 int d[maxn];
    56 
    57 int cal_d() {
    58     int L = strlen(S);
    59     d[L] = 1;
    60     for(int i = L-1; i >= 0; i--){
    61         vector<int> p;
    62         T.find_prefixes(S+i, L-i, p);
    63         for(int j = 0; j < p.size(); j++)  {
    64             d[i] = (d[i] + d[i + p[j]]) % M;
    65         }
    66     }
    67     return d[0];
    68 }
    69 int main(int argc, const char * argv[]) {
    70     int tt = 0;
    71     while(scanf("%s", S) == 1){
    72         T.clear();
    73         memset(d, 0, sizeof d);
    74         int m;
    75         scanf("%d", &m);
    76         for(int i = 0; i < m; i++) {
    77             scanf("%s", s);
    78             T.insert(s, strlen(s));
    79         }
    80         int ans = cal_d();
    81         printf("Case %d: %d
    ", ++tt, ans);
    82     }
    83     return 0;
    84 }

    解题思路:

      令d(i)表示从字符i开始的字符串(即S[i...L])的分解方案数。

      则状态转移方程:

      d(i) = sum{d(i+len(x)) | x为S[i..L]的前缀}

  • 相关阅读:
    实体类调用泛型父类中的静态方法中执行CRUD——第一版
    Windows10 磁盘100%解决办法
    Torchvision 源码安装[Ubuntu]
    Pycharm调试:进入调用函数后返回
    Windows 10 家庭版/专业版 彻底关闭windows update自动更新
    Windows10 家庭版 关闭Windows defender
    Windows 10 更改系统文字大小
    Ubuntu 使用命令行连接无线网
    支持向量机(SVM)
    Ubuntu系统实现将Jupyter notebook项目发布到GitHub
  • 原文地址:https://www.cnblogs.com/Kiraa/p/6046349.html
Copyright © 2011-2022 走看看