EOJ Problem #3261 分词 trie + dp + 小剪枝
http://acm.ecnu.edu.cn/problem/3261/
分词
Time limit per test: 1.0 seconds
Time limit all tests: 1.0 seconds
Memory limit: 256 megabytes
有一句句子因为粘贴的时候出现了一点问题空格全部丢失了。现在给一本字典,每个词都对应这个词出现的频率(每十亿)。根据这个频率,我们可以根据下面的公式算出这个词带来的收益 P(word) :
其中 frequency 就是上面所提到的频率。len
指的是单词的长度。
特别的,对于字典中没有出现过的词,P(word)=0 。
请对句子进行适当的分割,使得分割得到的所有词收益之和最大。同一个词可以重复出现,收益算作多次。
Input
先给出一本词典,词典的第一行是词条数(词条数约为 40 000 ),下面每行分别是单词和对应出现频率,用空格隔开。单词中只会出现英文字母大小写,不会有多余的空格。每个单词只会出现一次。频率是一个正实数。
所有单词长度之和不超过 3⋅105
,最长单词长度不超过 30
。
接下来一行一个整数 T (T≤10)
,表示有 T
个查询。
下面 T 行,每行一个句子,句子长度不超过 5 000
。句子中保证只含有英文字母大小写。注意单词匹配时,不区分大小写。
词典数据来源于 Wikipedia Project Gutenberg(可能需要代理),其中 1-10000 词汇。
查询数据来源于 IELTS Test。
Output
对于每组数据,输出两行。
第一行是一个实数,表示最大能达到的收益。输出和答案相差不超过 10−3
即可认为正确。
第二行输出一连串单词,单词和单词之间用空格隔开。满足:
- 把这些单词依次串联起来可以得到原句子;
- 所有单词的收益值相加得到第一行的实数。
Examples
5
ano 10
ther 30
another 10
an 300
other 20
1
another
112.826670
another
5
ano 10.0
ther 30.0
another 10.0
an 300.0
other 2000.0
1
another
212.837691
an other
Note
样例给出的词典与测试数据有所不同。
Source
2017 华东师范大学网赛
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <assert.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL; #include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
#include <bitset>
const int maxn = 4e5 + ;
const int N = ;
char str[maxn];
struct Node {
double val;
struct Node * pNext[N];
} tree[maxn];
int t;
struct Node * create() {
struct Node *p = &tree[t++];
p->val = ;
return p;
}
void toInsert(struct Node **T, char str[], double val, int lenstr) {
struct Node *p = *T;
if (!p) p = *T = create();
for (int i = ; str[i]; ++i) {
int id = str[i] - 'a';
if (!p->pNext[id]) p->pNext[id] = create();
p = p->pNext[id];
}
p->val = max(p->val, val);
}
double ask(struct Node *T, char str[], int be, int en) {
if (en - be + > ) return ;
struct Node *p = T;
if (!p) return ;
for (int i = be; i <= en; ++i) {
int id = str[i] - 'a';
if (!p->pNext[id]) return ;
p = p->pNext[id];
}
return p->val;
}
struct ddpp {
double val;
int pre;
} dp[maxn];
int del[maxn], DFN;
bool isok(char ch) {
return ch >= 'A' && ch <= 'Z' || ch >= 'a' && ch <= 'z';
} void toChange(char str[], int lenstr) {
for (int i = ; i <= lenstr; ++i) {
if (str[i] >= 'A' && str[i] <= 'Z') {
str[i] += ;
}
}
}
char sub[maxn];
void work() {
int n;
scanf("%d", &n);
struct Node *T = NULL;
for (int i = ; i <= n; ++i) {
scanf("%s", str + );
double val;
scanf("%lf", &val);
int lenstr = strlen(str + );
toChange(str, lenstr);
toInsert(&T, str, lenstr * lenstr * log(val), lenstr);
}
int q;
scanf("%d", &q);
while (q--) {
scanf("%s", str + );
int lenstr = strlen(str + );
strcpy(sub + , str + );
toChange(str, lenstr);
for (int i = ; i <= lenstr; ++i) {
dp[i].val = dp[i].pre = ;
for (int j = ; j <= i; ++j) {
double res = ask(T, str, j, i);
if (dp[i].val < dp[j - ].val + res) {
dp[i].val = dp[j - ].val + res;
dp[i].pre = j - ;
}
}
}
++DFN;
int pre = dp[lenstr].pre;
while (pre > ) {
del[pre] = DFN;
pre = dp[pre].pre;
}
printf("%0.10f\n", dp[lenstr].val);
for (int i = ; i <= lenstr; ++i) {
if (del[i - ] == DFN) {
printf(" ");
}
printf("%c", sub[i]);
}
printf("\n");
}
} int main() {
#ifdef local
freopen("data.txt", "r", stdin);
#endif
work();
return ;
}
EOJ Problem #3261 分词 trie + dp + 小剪枝的更多相关文章
- EOJ Problem #3249 状态压缩+循环周期+反向递推
限量供应 Time limit per test: 4.0 seconds Time limit all tests: 4.0 seconds Memory limit: 256 megabytes ...
- UVA 3942 Remember the Word (Trie+DP)题解
思路: 大白里Trie的例题,开篇就是一句很容易推出....orz 这里需要Trie+DP解决. 仔细想想我们可以得到dp[i]=sum(dp[i+len[x]]). 这里需要解释一下:dp是从最后一 ...
- EOJ 3261 分词
字典树,$dp$. 记录$dp[i]$为以$i$为结尾获得的最大价值.枚举结尾一段是哪个单词,更新最大值.可以将字典中单词倒着建一棵字典树. 这题数据有点不严谨. 下面这组数据答案应该是负的. 3 a ...
- UVALive - 3942 Remember the Word[Trie DP]
UVALive - 3942 Remember the Word Neal is very curious about combinatorial problems, and now here com ...
- hdu 4540 威威猫系列故事——打地鼠 dp小水题
威威猫系列故事——打地鼠 Time Limit: 300/100 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others) Total ...
- 四维dp 或者 剪枝 + dfs Codeforces Beta Round #6 (Div. 2 Only) D
http://codeforces.com/contest/6/problem/D 题目大意:有一队人,排成一列,每个人都有生命值,你每次可以攻击2~n位置的一个的人,假设每次攻击的位置为pos,那么 ...
- EOJ Monthly 2018.4 (E.小迷妹在哪儿(贪心&排序&背包)
ultmaster 男神和小迷妹们玩起了捉迷藏的游戏. 小迷妹们都希望自己被 ultmaster 男神发现,因此她们都把自己位置告诉了 ultmaster 男神,因此 ultmaster 男神知道了自 ...
- LightOJ - 1322 - Worst Case Trie(DP)
链接: https://vjudge.net/problem/LightOJ-1322 题意: In Computer Science Trie or prefix tree is a data st ...
- zoj3777 Problem Arrangement(状压dp,思路赞)
The 11th Zhejiang Provincial Collegiate Programming Contest is coming! As a problem setter, Edward i ...
随机推荐
- Speaking 1
What clothes do you usually like to wear?Well I like fashionable clothes, but I also want to be comf ...
- hdu-3078 Network(lca+st算法+dfs)
题目链接: Network Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) P ...
- python处理时间汇总
1.将字符串的时间转换为时间戳 方法: a = "2013-10-10 23:40:00" 将其转换为时间数组 import time timeArray = time.strpt ...
- zero to one (3)
工具使用 AWVS Acunetix Web Vulnerability Scanner(简称AWVS)是一款知名的Web网络漏洞扫描工具,它通过网络爬虫测试你的网站安全,检测流行安全漏洞. 功能及特 ...
- AtCoder Grand Contest #026 A - Colorful Slimes 2
Time Limit: 2 sec / Memory Limit: 1024 MB Score : 200200 points Problem Statement Takahashi lives in ...
- Azure一个Cloud Service支持多个公网地址
Azure刚刚发布在同一个Cloud Service下支持多个公网IP地址的功能. 这个功能主要是用于: 当相同的端口需要公用相同的LoadBalance时. 比如: 一种使用场景是多组Web服务器被 ...
- Docker入门(四):服务(Services)
这个<Docker入门系列>文档,是根据Docker官网(https://docs.docker.com)的帮助文档大致翻译而成.主要是作为个人学习记录.有错误的地方,Robin欢迎大家指 ...
- c# 鼠标点击控件即拖动窗体
在编程中,有时打开的窗体没有边框,但是我们仍然想在鼠标放在窗体上就能拖动窗体,这样我们只需要以窗体中的一个控件为参考,我们在这里以panel为例子: public class PanelNew : P ...
- Python 如何连接并操作 Aws 上 PB 级云数据仓库 Redshift
Python 如何连接并操作 Aws 上 PB 级云数据仓库 Redshift 一.简介 Amazon Redshift 是一个快速.可扩展的数据仓库,可以简单.经济高效地分析数据仓库和数据湖中的所有 ...
- matlab新手入门(二)(翻译)
矩阵和数组 MATLAB是“矩阵实验室”的缩写.虽然其他编程语言大多数一次使用数字,但MATLAB®主要用于整个矩阵和数组.所有MATLAB变量都是多维数组,无论数据类型如何.矩阵是通常用于线性代数的 ...