【暑假】[实用数据结构]UVAlive 3942 Remember the Word
UVAlive 3942 Remember the Word
题目:
Time Limit: 3000MS | Memory Limit: Unknown | 64bit IO Format: %lld & %llu |
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 , 1S
4000 .
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。- 代码:
- #include<cstdio>
- #include<cstring>
- #include<vector>
- #define FOR(a,b,c) for(int a=(b);a<(c);a++)
- using namespace std;
- const int maxnode = * + ;
- const int sigma_size = ;
- // 字母表为全体小写字母的Trie
- struct Trie {
- int ch[maxnode][sigma_size];
- int val[maxnode];
- int sz;
- void clear() { sz = ; memset(ch[], , sizeof(ch[])); }
- int idx(char c) { return c - 'a'; }
- void insert(const char *s, int v) {
- int u = , n = strlen(s);
- for(int i = ; i < n; i++) {
- int c = idx(s[i]);
- if(!ch[u][c]) {
- memset(ch[sz], , sizeof(ch[sz]));
- val[sz] = ;
- ch[u][c] = sz++;
- }
- u = ch[u][c];
- }
- val[u] = v;
- }
- // 找字符串s的长度不超过len的前缀
- void find_prefixes(const char *s, int len, vector<int>& ans) { //构造ans
- int u = ;
- for(int i = ; i < len; i++) {
- if(s[i] == '\0') break;
- int c = idx(s[i]);
- if(!ch[u][c]) break; //不存在该字符 查找失败退出
- u = ch[u][c]; //否则往下找
- if(val[u] != ) ans.push_back(val[u]); // 找到一个前缀
- }
- }
- //find_prefixes操作以vector形式返回满足要求的字串标号val
- //find操作需要对查找操作进行长度限制 以节省时间
- };
- const int maxl= + ;
- const int maxw= +; //单词个数
- const int maxwl= + ;
- const int MOD = ;
- char text[maxl];
- int d[maxl],len[maxw];
- Trie trie;
- int main(){
- int kase=,n;
- while(scanf("%s%d",text,&n)==){
- trie.clear(); //clear()
- char word[maxwl];
- FOR(i,,n+){ //标号为1..n
- scanf("%s",word);
- len[i]=strlen(word); //记录word长度 节约了一个char[][]
- trie.insert(word,i); //构造Trie val为word标号
- }
- // DP
- memset(d,,sizeof(d));
- int L=strlen(text);
- d[L]=; // ? :DP边界 只要后缀中有前缀单词 则 += 1
- for(int i=L-;i>=;i--){
- vector<int> p; //存储
- trie.find_prefixes(text+i,L-i,p);
- //寻找在后缀text+i中以前缀形势出现过的所有单词 //text+i为字串text[i..L)
- FOR(j,,p.size())
- d[i] = (d[i]+d[i+len[p[j]]]) % MOD; //i+len-1为单词尾
- }
- printf("Case %d: %d\n",++kase,d[]);
- }
- return ;
- }
【暑假】[实用数据结构]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 wit ...
- UVALive - 3942 Remember the Word[Trie DP]
UVALive - 3942 Remember the Word Neal is very curious about combinatorial problems, and now here com ...
- UVALive 3942 Remember the Word 字典树+dp
/** 题目:UVALive 3942 Remember the Word 链接:https://vjudge.net/problem/UVALive-3942 题意:给定一个字符串(长度最多3e5) ...
- 【暑假】[实用数据结构]UVAlive 3027 Corporative Network
UVAlive 3027 Corporative Network 题目: Corporative Network Time Limit: 3000MS Memory Limit: 30000K ...
- 【暑假】[实用数据结构]UVAlive 4670 Dominating Patterns
UVAlive 4670 Dominating Patterns 题目: Dominating Patterns Time Limit: 3000MS Memory Limit: Unkn ...
- 【暑假】[实用数据结构]UVAlive 3135 Argus
UVAlive 3135 Argus Argus Time Limit: 3000MS Memory Limit: Unknown 64bit IO Format: %lld & %l ...
- 【暑假】[实用数据结构]UVAlive 3026 Period
UVAlive 3026 Period 题目: Period Time Limit: 3000MS Memory Limit: Unknown 64bit IO Format: %lld ...
- 【暑假】[实用数据结构]UVAlive 4329 Ping pong
UVAlive 4329 Ping pong 题目: Ping pong Time Limit: 3000MS Memory Limit: Unknown 64bit IO Format: % ...
- 【暑假】[实用数据结构]UVAlive 3644 X-Plosives
UVAlive X-Plosives 思路: “如果车上存在k个简单化合物,正好包含k种元素,那么他们将组成一个易爆的混合物” 如果将(a,b)看作一条边那么题意就是不能出现环,很容易联想到K ...
随机推荐
- 1022: [SHOI2008]小约翰的游戏John - BZOJ
Description 小约翰经常和他的哥哥玩一个非常有趣的游戏:桌子上有n堆石子,小约翰和他的哥哥轮流取石子,每个人取的时候,可以随意选择一堆石子,在这堆石子中取走任意多的石子,但不能一粒石子也不取 ...
- CSS文件和Javascript文件的压缩
像JQuery一样来压缩我们的CSS和JS 我们都知道一般JQuery新版本发布的时候往往会有几个不同类型文件,比如原始版本文件.最小文件以及其他配合IDE智能提示的各种版本文件,前期我们使用JQue ...
- Firefly Http通信简单介绍
原地址:http://www.9miao.com/question-15-54042.html 首先创建firefly工程,firefly-admin.py createproject httptes ...
- Injection Attacks-Log 注入
日志注入(也称日志文件注入) 很多应用都维护着一系列面向授权用户.通过 HTML 界面展示的日志,因而成为了攻击者的首要目标,这些攻击者试图伪装其他攻击.误导日志读者,甚至对阅读和分析日志监测应用的用 ...
- nagios plugins之 check_http
nagios下的check_http ZT具体参数是一个比较重要的点,我带大家来看看.. //显示版本 #./check_http -V check_http v2053 (nagios-plugin ...
- linux查找某个文件中单词出现的次数
文件名称:list 查找单词名称:test 操作命令: (1)more list | grep -o test | wc -l (2)cat list | grep -o test | wc -l ( ...
- 在服务器端使用 Git 创建源代码仓库
下面简单讲述在服务器搭建 Git 仓库的过程. 安装 Git 程序 Git 是分布式的,即程序不区分服务端和客户端,大部分 Linux 发行版的官方源里都有它,比如在 Archlinux 里安装 Gi ...
- Android:requestWindowFeature应用程序窗体显示状态操作
注意requestWindowFeature必须在 setContentView()之前调用. 1.DEFAULT_FEATURES:系统默认状态,一般不需要指定 2.FEATURE_CONTEXT_ ...
- visio2010去除直线交叉处的跨线
设计(最上方)->连接线(最右侧)->显示跨线(取消打钩)
- 转载:C++ vector 类学习笔记
声明:本文转载自http://blog.csdn.net/whz_zb/article/details/6827999 vector简介 vector是STL中最常见的容器,它是一种顺序容器,支持随机 ...