zoukankan      html  css  js  c++  java
  • UVALive

    给出一个长度不超过300000的字符串 S,然后给出 n 个长度不超过100的字符串。

    如果字符串可以多次使用,用这 n 个字符串组成 S 的方法数是多少?

     

    比如样例中,abcd = a + b + cd = ab + cd

    dp[i] 表示用这n个字符串构成,S中从 i ~ len之间的字母构成的子串,的可分解方案数。

    如果存在一个位置 x >= i, 且 i~x 之间的字母是一个单词,那么dp[i] = ∑ ( dp[x] )

    但是如果暴力枚举 i ~ x是不是一个单词,必然会TLE。这时我们就需要 Trie 树优化这个DP。

    #include <iostream>
    #include <cstdlib>
    #include <cstdio>
    #include <cmath>
    #include <cstring>
    using namespace std;
    #define maxn 400000 + 100
    #define sigma_size 27
    #define LL long long
    #define MOD 20071027
    
    int tot = 0;
    int trie[maxn][sigma_size], sum[maxn], dp[maxn];
    
    void insert(char s[])
    {
            int root = 0;
            for (int i = 0; s[i]; i++)
            {
                    int id = s[i]-'a';
                    if (!trie[root][id])
                    {
                            sum[++tot] = 0;
                            trie[root][id] = tot;
                    }
                    root = trie[root][id];
            }
            sum[root] = 1;
    }
    
    void found(char s[], int k)
    {
            int root = 0;
            for (int i = k; s[i]; i++)
            {
                    int id = s[i]-'a';
                    if (!trie[root][id])
                            return;
                    root = trie[root][id];
                    if (sum[root])
                            dp[k] = (dp[k]+dp[i+1])%MOD;
            }
    }
    
    int main()
    {
            char s[maxn];
            int len, ca = 0;
            while(scanf("%s", s) != EOF)
            {
                    char t[maxn];
                    int n;
                    scanf("%d", &n);
    
                    memset(trie, 0, sizeof(trie));
                    memset(sum, 0, sizeof(sum));
                    for (int i = 1; i <= n; i++)
                    {
                            scanf("%s", t);
                            insert(t);
                    }
    
                    memset(dp, 0, sizeof(dp));
    
                    len = strlen(s);
    
                    dp[len] = 1;
                    for (int i = len-1; i >= 0; i--)
                            found(s, i);
    
                    printf("Case %d: %d
    ", ++ca, dp[0]);
            }
    }
  • 相关阅读:
    unity c# 获取系统时间
    如果你想让继承MonoBehaviour的类变成Singleten
    关于程序员
    开始养成记录的习惯吧
    关于结构体的赋值问题
    数学中的集合,群,环,域
    励志
    [编程题] 进制均值
    javaEE 入门
    jsp内置对象2
  • 原文地址:https://www.cnblogs.com/ruthank/p/9469084.html
Copyright © 2011-2022 走看看