hdu 4117 -- GRE Words (AC自动机+线段树)
problem
Now George is working on a word list containing N words.
He has so poor a memory that it is too hard for him to remember all of the words on the list. But he does find a way to help him to remember. He finds that if a sequence of words has a property that for all pairs of neighboring words, the previous one is a substring of the next one, then the sequence of words is easy to remember.
So he decides to eliminate some words from the word list first to make the list easier for him. Meantime, he doesn't want to miss the important words. He gives each word an importance, which is represented by an integer ranging from -1000 to 1000, then he wants to know which words to eliminate to maximize the sum of the importance of remaining words. Negative importance just means that George thought it useless and is a waste of time to recite the word.
Note that although he can eliminate any number of words from the word list, he can never change the order between words. In another word, the order of words appeared on the word list is consistent with the order in the input. In addition, a word may have different meanings, so it can appear on the list more than once, and it may have different importance in each occurrence.
Input
The first line contains an integer T(1 <= T <= 50), indicating the number of test cases.
Each test case contains several lines.
The first line contains an integer N(1 <= N <= 2 * 10 4), indicating the number of words.
Then N lines follows, each contains a string S i and an integer W i, representing the word and its importance. S i contains only lowercase letters.
You can assume that the total length of all words will not exceeded 3 * 10 5.
Output
For each test case in the input, print one line: "Case #X: Y", where X is the test case number (starting with 1) and Y is the largest importance of the remaining sequence of words.
Sample Input
1
5
a 1
ab 2
abb 3
baba 5
abbab 8
Sample Output
Case #1: 14 思路:AC自动机+线段树。这题直观的想法是以每个字符串为尾串,求在当前串之前选取字符串并以当前串为结束得到的最大值,即dp[i]=max(dp[j])+w[i],s[j]是s[i]的子串且j<i;
我们可以反向建立fail树,那么对于串s[i]的最后一位指向的孩子,均是包含s[i]的串,所以以s[i]的最后一位为根节点的子树中的孩子节点表示的串均包含s[i],那么我们对串s[1]~s[n]逐一进行计算时,可以把结
果用线段树更新到子树中,然后对于每个串计算时,只需要考虑s[i]的每一位能得到的最大值(线段树单点查询),最后取最大值加上w[i],即为s[i]的最大值,然后更新到子树中。 代码如下:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <queue>
using namespace std;
typedef long long LL;
const int N=2e4+;
const int M=3e5+;
char s[M];
int w[N],pos[N]; struct Node
{
int son[];
}node[M];
int fail[M];
int root,tot; struct Edge
{
int to;
int next;
}edge[M];
int head[M],cnt; int in[M],out[M],tp; ///树节点序号化; int tx[M*],tf[M*],L,R,tmp; ///线段树; inline int newnode()
{
tot++;
memset(node[tot].son,,sizeof(node[tot].son));
fail[tot]=;
return tot;
} inline void addEdge(int u,int v)
{
edge[cnt].to=v;
edge[cnt].next=head[u];
head[u]=cnt++;
} inline void insert(char s[])
{
int now=root;
for(int i=;s[i];i++)
{
if(!node[now].son[s[i]-'a'])
node[now].son[s[i]-'a']=newnode();
now=node[now].son[s[i]-'a'];
}
}
inline void build()
{
queue<int>Q;
Q.push(root);
while(!Q.empty())
{
int now=Q.front(); Q.pop();
if(now!=root) addEdge(fail[now],now);
for(int i=;i<;i++)
{
if(node[now].son[i])
{
if(now!=root)
fail[node[now].son[i]]=node[fail[now]].son[i];
Q.push(node[now].son[i]);
}
else node[now].son[i]=node[fail[now]].son[i]; }
}
}
inline void dfs(int now)
{
in[now]=++tp;
for(int i=head[now];i;i=edge[i].next)
{
dfs(edge[i].to);
}
out[now]=tp;
}
inline void pushdown(int i)
{
if(!tf[i]) return ;
int pre=tf[i];
tf[i<<]=max(tf[i<<],pre);
tf[i<<|]=max(tf[i<<|],pre);
tx[i<<]=max(tx[i<<],pre);
tx[i<<|]=max(tx[i<<|],pre);
tf[i]=;
}
inline int query(int l,int r,int i)
{
if(l==r) return tx[i];
int mid=(l+r)>>;
pushdown(i);
if(L<=mid) return query(l,mid,i<<);
else return query(mid+,r,i<<|);
}
inline void update(int l,int r,int i)
{
if(L<=l&&r<=R)
{
tf[i]=max(tf[i],tmp);
tx[i]=max(tx[i],tmp);
return ;
}
int mid=(l+r)>>;
pushdown(i);
if(L<=mid) update(l,mid,i<<);
if(R>mid) update(mid+,r,i<<|);
tx[i]=max(tx[i<<],tx[i<<|]);
} void init()
{
tot=-;
cnt=;
tp=;
root=newnode();
memset(head,,sizeof(head));
memset(fail,,sizeof(fail));
memset(tx,,sizeof(tx));
memset(tf,,sizeof(tf));
}
int main()
{
int T,Case=; scanf("%d",&T);
while(T--)
{
init();
int n; scanf("%d",&n);
for(int i=;i<=n;++i)
{
scanf("%s%d",s+pos[i-],w+i);
pos[i]=pos[i-]+strlen(s+pos[i-]);
insert(s+pos[i-]);
}
build();
dfs(root);
int ans=;
for(int i=;i<=n;++i)
{
tmp=;
int now=root;
for(int j=pos[i-];j<pos[i];++j)
{
now=node[now].son[s[j]-'a'];
L=in[now]; R=in[now];
int res=query(,tp,);
tmp=max(tmp,res);
}
tmp+=w[i];
ans=max(ans,tmp);
L=in[now];
R=out[now];
update(,tp,);
}
printf("Case #%d: %d\n",Case++,ans);
}
return ;
}
hdu 4117 -- GRE Words (AC自动机+线段树)的更多相关文章
- hdu 4117 GRE Words AC自动机DP
题目:给出n个串,问最多能够选出多少个串,使得前面串是后面串的子串(按照输入顺序) 分析: 其实这题是这题SPOJ 7758. Growing Strings AC自动机DP的进阶版本,主题思想差不多 ...
- HDU4117 GRE WORDS(AC自动机+线段树维护fail树的dfs序)
Recently George is preparing for the Graduate Record Examinations (GRE for short). Obviously the mos ...
- hdu 4117 GRE Words (ac自动机 线段树 dp)
参考:http://blog.csdn.net/no__stop/article/details/12287843 此题利用了ac自动机fail树的性质,fail指针建立为树,表示父节点是孩子节点的后 ...
- HDU 5069 Harry And Biological Teacher(AC自动机+线段树)
题意 给定 \(n\) 个字符串,\(m\) 个询问,每次询问 \(a\) 字符串的后缀和 \(b\) 字符串的前缀最多能匹配多长. \(1\leq n,m \leq 10^5\) 思路 多串匹配,考 ...
- BZOJ2434:[NOI2011]阿狸的打字机(AC自动机,线段树)
Description 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母. 经阿狸研究发现,这个打字机是这样工作的 ...
- 背单词(AC自动机+线段树+dp+dfs序)
G. 背单词 内存限制:256 MiB 时间限制:1000 ms 标准输入输出 题目类型:传统 评测方式:文本比较 题目描述 给定一张包含N个单词的表,每个单词有个价值W.要求从中选出一个子序列使 ...
- hdu 2896 病毒侵袭 ac自动机
/* hdu 2896 病毒侵袭 ac自动机 从题意得知,模式串中没有重复的串出现,所以结构体中可以将last[](后缀链接)数组去掉 last[]数组主要是记录具有相同后缀模式串的末尾节点编号 .本 ...
- 【BZOJ2434】阿狸的打字机(AC自动机,树状数组)
[BZOJ2434]阿狸的打字机(AC自动机,树状数组) 先写个暴力: 每次打印出字符串后,就插入到\(Trie\)树中 搞完后直接搭\(AC\)自动机 看一看匹配是怎么样的: 每次沿着\(AC\)自 ...
- hdu 5274 Dylans loves tree(LCA + 线段树)
Dylans loves tree Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Othe ...
随机推荐
- 201521123054 《Java程序设计》第9周学习总结
1. 本周学习总结 2. 书面作业 题目5-1 1.1 截图你的提交结果(出现学号) 1.2 自己以前编写的代码中经常出现什么异常.需要捕获吗(为什么)?应如何避免? 经常会出现ArrayIndexO ...
- Android 跳转系统选择本地视频的功能
今天在项目开发的过程中产品要求添加选择本地视频的功能,于是就翻阅和查找各种资料,进行功能的开发,但是在开发过程中发现,各种不同的品牌的手机跳转至系统选择本地视频的功能结果不太一样,所以我就对一些主流的 ...
- Mybatis第七篇【resultMap、resultType、延迟加载】
resultMap 有的时候,我们看别的映射文件,可能看不到以下这么一段代码: <resultMap id="userListResultMap" type="us ...
- IDEA运行编译后配置文件无法找到,或配置文件修改后无效的问题
1.触发事件 今天正好在学习log4j,为了测试其配置文件log4j.properties中的各种配置,进行了频繁修改和程序启动以确认效果,因为是使用的IDEA建立的Web项目,接着问题就来了,配置文 ...
- websphere部署--web应用-以自己的项目为例
启动websphere: 1) 启动Manager: /home/wasadmin/IBM/WebSphere/AppServer/bin/startManager.sh 2) 启动Node: ...
- mongodb 3.4 集群搭建升级版 五台集群
最新版mongodb推荐使用yaml语法来做配置,另外一些旧的配置在最新版本中已经不在生效,所以我们在生产实际搭建mongodb集群的时候做了一些改进.如果大家不熟悉什么是分片.副本集.仲裁者的话请先 ...
- Maven(五)之Maven配置阿里云镜像飞快下jar包
用过Maven的人都知道Maven对于依赖的管理让我们程序员从此远离了自己去在项目中把需要的jar包导入到项目中,但是因为中央仓库是在国外的,所以在我们从中央仓库下载依赖的时候, 我们发现下载速度真的 ...
- SSM之框架整合
前言 SSM框架,即Spring + Spring MVC + MyBatis的整合框架集,是继SSH后比较主流的Java EE企业级框架,采用标准的MVC模式,项目结构与微软的ASP.NET MVC ...
- const的用法,特别是用在函数前面与后面的区别!
const的用法,特别是用在函数后面 在普通的非 const成员函数中,this的类型是一个指向类类型的 const指针.可以改变this所指向的值,但不能改变 this所保存的地址. 在 const ...
- UI自动化测试简介及Selenium工具的介绍和环境搭建
自动化测试简介 1.1何为自动化测试? 是把以人为驱动的测试转化为机器执行的一种过程,它是一种以程序测试程序的过程.换言之,就是以程序实现的方式来代替手工测试. 1.2自动化测试分类 分为功能自动化测 ...