UVa Live 3942 Remember the Word - Hash - 动态规划

Posted 阿波罗2003

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UVa Live 3942 Remember the Word - Hash - 动态规划相关的知识,希望对你有一定的参考价值。

题目传送门

  高速路出口I

  高速路出口II

题目大意

  给定若干种短串,和文本串$S$,问有多少种方式可以将短串拼成长串。

  显然,你需要一个动态规划。

  用$f[i]$表示拼出串$S$前$i$个字符的方案数。

  转移是显然的。枚举上一个拼接的串的长度,然后判断它是否存在,如果存在就把$f[i]$加上$f[i - l]$。

  这个判断存在可以用Hash。当然可以对每个短串的反串建立Trie树,然后在Trie树上查一查$i$往前会走到长度为哪些的终止状态。

  由于我懒,不想写Trie树,直接用平板电视的hash表,然后慢得起飞。

Code

 1 /**
 2  * UVa Live
 3  * Problem#3942
 4  * Accepted
 5  * Time: 603ms
 6  */
 7 #include <ext/pb_ds/assoc_container.hpp>
 8 #include <ext/pb_ds/hash_policy.hpp>
 9 #include <iostream>
10 #include <cstring>
11 #include <cstdlib>
12 #include <cstdio>
13 using namespace std;
14 using namespace __gnu_pbds;
15 typedef bool boolean;
16 
17 #define ui unsigned int
18 
19 const int N = 3e5 + 5, M = 20071027, L = 101;
20 const ui base = 200379;
21 
22 int n;
23 char S[N], buf[L];
24 ui ha[N], ps[N];
25 cc_hash_table<int, boolean> mp[L];
26 
27 inline void prepare() {
28     ps[0] = 1;
29     for (int i = 1; i < N; i++)
30         ps[i] = ps[i - 1] * base;
31 }
32 
33 inline boolean init() {
34     if (scanf("%s", S + 1) == EOF)    return false;
35     scanf("%d", &n);
36     for (int i = 1; i < L; i++)
37         mp[i].clear();
38     int l;
39     ui s;
40     for (int i = 1; i <= n; i++) {
41         scanf("%s", buf);
42         for (l = 0, s = 0; buf[l]; l++)
43            s = (s * base) + buf[l];
44         mp[l][s] = true;    
45     }
46     return true;
47 }
48 
49 int f[N];
50 inline void solve() {
51     f[0] = 1, ha[0] = 0;
52     n = strlen(S + 1);
53     for (int i = 1; i <= n; i++)
54         ha[i] = ha[i - 1] * base + S[i];
55     for (int i = 1; i <= n; i++) {
56         f[i] = 0;
57         for (int j = 1; j < L && j <= i; j++) {
58             ui s = ha[i] - ha[i - j] * ps[j];
59             if (mp[j].find(s) != mp[j].end())
60                 f[i] = (f[i] + f[i - j]) % M;
61         }
62     }
63     printf("%d\n", f[n]);
64 }
65 
66 int kase = 0;
67 int main() {
68     prepare();
69     while(init()) {
70         printf("Case %d: ", ++kase);
71         solve();
72     }
73     return 0;
74 }

以上是关于UVa Live 3942 Remember the Word - Hash - 动态规划的主要内容,如果未能解决你的问题,请参考以下文章

UVA 3942 -- Remember the Word (字典树+dp)

UVA3942 Remember the Word

LA 3942 && UVa 1401 Remember the Word (Trie + DP)

UVALive - 3942 Remember the Word[树状数组]

UVALive - 3942 Remember the Word[Trie DP]

3942 - Remember the Word