【暑假】[实用数据结构]UVAlive 3942 Remember the Word

UVAlive 3942 Remember the Word

题目:

Remember the Word

Time Limit: 3000MS   Memory Limit: Unknown   64bit IO Format: %lld & %llu

Submit Status

Description

Neal is very curious about combinatorial problems, and now here comes a problem about words. Knowing that Ray has a photographic memory and this may not trouble him, Neal gives it to Jiejie.

Since Jiejie can‘t remember numbers clearly, he just uses sticks to help himself. Allowing for Jiejie‘s only 20071027 sticks, he can only record the remainders of the numbers divided by total amount of sticks.

The problem is as follows: a word needs to be divided into small pieces in such a way that each piece is from some given set of words. Given a word and the set of words, Jiejie should calculate the number of ways the given word can be divided, using the words in the set.

Input

The input file contains multiple test cases. For each test case: the first line contains the given word whose length is no more than 300 000.

The second line contains an integer S , 1S4000 .

Each of the following S lines contains one word from the set. Each word will be at most 100 characters long. There will be no two identical words and all letters in the words will be lowercase.

There is a blank line between consecutive test cases.

You should proceed to the end of file.

Output

For each test case, output the number, as described above, from the task description modulo 20071027.

Sample Input

abcd
4
a
b
cd
ab

Sample Output

Case 1: 2

思路: 将一个字符串按照所给单词分解,求解有多少种分解方案。DP + Trie加速。定义d[i]为后缀i的分解方案数,可以得到状态转移方程:  d[i] += d[i+len[x]] 其中x为后缀i前缀的标号,len为标号为x的单词长度。 但如何快速确定后缀i的前缀呢?这里用到了Trie,在find(后缀i)的路径上有val标记的都为后缀i的前缀,只需要O(n)的时间可以构造出p。

代码:
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<vector>
 4 #define FOR(a,b,c) for(int a=(b);a<(c);a++)
 5 using namespace std;
 6
 7 const int maxnode = 4000 * 100 + 10;
 8 const int sigma_size = 26;
 9
10 // 字母表为全体小写字母的Trie
11 struct Trie {
12   int ch[maxnode][sigma_size];
13   int val[maxnode];
14   int sz;
15   void clear() { sz = 1; memset(ch[0], 0, sizeof(ch[0])); }
16   int idx(char c) { return c - ‘a‘; }
17
18   void insert(const char *s, int v) {
19     int u = 0, n = strlen(s);
20     for(int i = 0; i < n; i++) {
21       int c = idx(s[i]);
22       if(!ch[u][c]) {
23         memset(ch[sz], 0, sizeof(ch[sz]));
24         val[sz] = 0;
25         ch[u][c] = sz++;
26       }
27       u = ch[u][c];
28     }
29     val[u] = v;
30   }
31
32   // 找字符串s的长度不超过len的前缀
33   void find_prefixes(const char *s, int len, vector<int>& ans) { //构造ans
34     int u = 0;
35     for(int i = 0; i < len; i++) {
36       if(s[i] == ‘\0‘) break;
37       int c = idx(s[i]);
38       if(!ch[u][c]) break;       //不存在该字符 查找失败退出
39       u = ch[u][c];              //否则往下找
40       if(val[u] != 0) ans.push_back(val[u]); // 找到一个前缀
41     }
42   }
43   //find_prefixes操作以vector形式返回满足要求的字串标号val
44   //find操作需要对查找操作进行长度限制 以节省时间
45 };
46
47 const int maxl= 300000 + 10;
48 const int maxw= 4000+10;    //单词个数
49 const int maxwl=100 + 10;
50 const int MOD = 20071027;
51
52 char text[maxl];
53 int d[maxl],len[maxw];
54 Trie trie;
55
56 int main(){
57 int kase=0,n;
58   while(scanf("%s%d",text,&n)==2){
59       trie.clear();   //clear()
60       char word[maxwl];
61       FOR(i,1,n+1){   //标号为1..n
62           scanf("%s",word);
63           len[i]=strlen(word);    //记录word长度 节约了一个char[][]
64           trie.insert(word,i);   //构造Trie val为word标号
65       }
66
67       // DP
68       memset(d,0,sizeof(d));
69       int L=strlen(text);
70       d[L]=1;   // ? :DP边界 只要后缀中有前缀单词 则 += 1
71       for(int i=L-1;i>=0;i--){
72           vector<int> p;                     //存储
73           trie.find_prefixes(text+i,L-i,p);
74         //寻找在后缀text+i中以前缀形势出现过的所有单词 //text+i为字串text[i..L)
75           FOR(j,0,p.size())
76             d[i] = (d[i]+d[i+len[p[j]]]) % MOD;  //i+len-1为单词尾
77       }
78       printf("Case %d: %d\n",++kase,d[0]);
79   }
80   return 0;
81 } 

				
时间: 2024-10-14 04:39:58

【暑假】[实用数据结构]UVAlive 3942 Remember the Word的相关文章

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

UVALive - 3942 Remember the Word A potentiometer, or potmeter for short, is an electronic device with a variable electric resistance. It has two terminals and some kind of control mechanism (often a dial, a wheel or a slide) with which the resistance

UVALive 3942 - Remember the Word(DP,数组Trie+指针Trie)

UVALive 3942 - Remember the Word(DP,数组Trie+指针Trie) ACM 题目地址: UVALive 3942 - Remember the Word 题意: 给一些单词,然后给一个长的单词,问有几种方法能组成这个大单词,单词可以重复用. 分析: DP[i]=sum{DP[j} (i<j<len),从后往前求. 本来用数组Trie写得爽爽的,1A了. 发现2s多,不能忍! 然后用指针Trie写了一遍,各种出错,整个人都不好了... 研究了一遍别人代码,发现快

UVALive 3942 Remember the Word 字典树+dp

/** 题目:UVALive 3942 Remember the Word 链接:https://vjudge.net/problem/UVALive-3942 题意:给定一个字符串(长度最多3e5)和m个单词(每个单词长度最多100).单词都是不同的.该字符串可以由若干个单词组成,问最多有多少种组合方式. 思路:字典树+dp 用字典树处理好m个单词,定义dp[i]表示从i开始的字符串可以由单词组成的方式数. 那么dp[i] += dp[i+j]; j表示某个单词和字符串的[i,i+j-1]匹配

UVALive - 3942 Remember the Word[Trie DP]

UVALive - 3942 Remember the Word Neal is very curious about combinatorial problems, and now here comes a problem about words. Know- ing that Ray has a photographic memory and this may not trouble him, Neal gives it to Jiejie. Since Jiejie can’t remem

UVALive - 3942 - Remember the Word (Trie树)

UVALive - 3942 Remember the Word Time Limit: 3000MS   Memory Limit: Unknown   64bit IO Format: %lld & %llu Submit Status Description Neal is very curious about combinatorial problems, and now here comes a problem about words. Knowing that Ray has a p

【暑假】[实用数据结构]UVAlive 3027 Corporative Network

UVAlive 3027 Corporative Network 题目:   Corporative Network Time Limit: 3000MS   Memory Limit: 30000K Total Submissions: 3450   Accepted: 1259 Description A very big corporation is developing its corporative network. In the beginning each of the N ent

【暑假】[实用数据结构]UVAlive

题目:   Dominating Patterns Time Limit: 3000MS   Memory Limit: Unknown   64bit IO Format: %lld & %llu Submit Status Description The archaeologists are going to decipher a very mysterious ``language". Now, they know many language patterns; each patt

【暑假】[实用数据结构]UVAlive 3026 Period

UVAlive 3026 Period 题目: Period Time Limit: 3000MS   Memory Limit: Unknown   64bit IO Format: %lld & %llu Submit Status Description For each prefix of a given string S with N characters (each character has an ASCII code between 97 and 126, inclusive),

【暑假】[实用数据结构]UVAlive 3135 Argus

UVAlive 3135 Argus Argus Time Limit: 3000MS   Memory Limit: Unknown   64bit IO Format: %lld & %llu Submit Status Description A data stream is a real-time, continuous, ordered sequence of items. Some examples include sensor data, Internet traffic, fin