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 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。 代码:
 #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的更多相关文章

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

    UVALive - 3942 Remember the Word A potentiometer, or potmeter for short, is an electronic device wit ...

  2. UVALive - 3942 Remember the Word[Trie DP]

    UVALive - 3942 Remember the Word Neal is very curious about combinatorial problems, and now here com ...

  3. UVALive 3942 Remember the Word 字典树+dp

    /** 题目:UVALive 3942 Remember the Word 链接:https://vjudge.net/problem/UVALive-3942 题意:给定一个字符串(长度最多3e5) ...

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

    UVAlive 3027 Corporative Network 题目:   Corporative Network Time Limit: 3000MS   Memory Limit: 30000K ...

  5. 【暑假】[实用数据结构]UVAlive 4670 Dominating Patterns

    UVAlive 4670 Dominating Patterns 题目:   Dominating Patterns   Time Limit: 3000MS   Memory Limit: Unkn ...

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

    UVAlive 3135 Argus Argus Time Limit: 3000MS   Memory Limit: Unknown   64bit IO Format: %lld & %l ...

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

    UVAlive 3026 Period 题目: Period   Time Limit: 3000MS   Memory Limit: Unknown   64bit IO Format: %lld ...

  8. 【暑假】[实用数据结构]UVAlive 4329 Ping pong

    UVAlive 4329 Ping pong 题目: Ping pong Time Limit: 3000MS   Memory Limit: Unknown   64bit IO Format: % ...

  9. 【暑假】[实用数据结构]UVAlive 3644 X-Plosives

    UVAlive X-Plosives 思路:    “如果车上存在k个简单化合物,正好包含k种元素,那么他们将组成一个易爆的混合物”  如果将(a,b)看作一条边那么题意就是不能出现环,很容易联想到K ...

随机推荐

  1. 1063: [Noi2008]道路设计 - BZOJ

    Description Z 国坐落于遥远而又神奇的东方半岛上,在小Z 的统治时代公路成为这里主要的交通手段.Z 国共有n 座城市,一些城市之间由双向的公路所连接.非常神奇的是Z 国的每个城市所处的经度 ...

  2. 引用外部CSS的link和import方式的分析与比较

    很多网页中的 CSS 链接与引用是这样写的: <style type="text/css" media="screen"> @import url( ...

  3. spoj 1436

    用并查集看一下是否会围成一个环  若围成环直接输出NO   当然 当 m >= n  时必然会围成环直接输出NO #include <algorithm> #include < ...

  4. C++11的for循环,以及范围Range类的实现

    C++11支持range-based for循环.这是一个很方便的特性,能省挺多代码.以下代码就能很方便的遍历vector中的元素,并打印出来: 1 2 3 4 5 6 7 8 std::vector ...

  5. memmove 和 memcpy的区别

    memcpy和memmove()都是C语言中的库函数,在头文件string.h中,作用是拷贝一定长度的内存的内容,原型分别如下:void *memcpy(void *dst, const void * ...

  6. ajax返回正个页面

       

  7. linux 修改命令行编码 乱码解决方案

    修改/etc/default/locale命令:sudo vim /etc/default/locale1将下面这两行 LANG=zh_CN.UTF-8 LANGUAGE=zh_CN:zh 修改为: ...

  8. thread dump

    最近在做性能测试,需要对线程堆栈进行分析,在网上收集了一些资料,学习完后,将相关知识整理在一起,输出文章如下. 一.Thread Dump介绍 1.1什么是Thread Dump? Thread Du ...

  9. Servlet课程0424(一) 通过实现Servlet接口来开发Servlet

    //这是我的第一个Servlet,使用实现Servlet接口的方式来开发 package com.tsinghua; import javax.servlet.*; import java.io.*; ...

  10. Maven学习总结(四)——Maven核心概念

    一.Maven坐标 1.1.什么是坐标? 在平面几何中坐标(x,y)可以标识平面中唯一的一点. 1.2.Maven坐标主要组成 groupId:组织标识(包名) artifactId:项目名称 ver ...