HDU4117 GRE WORDS(AC自动机+线段树维护fail树的dfs序)
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.
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.OutputFor 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
题解:
给定n个字符串,要求按顺序取一些字符串,满足后一个字符串是前一个字符串的子串,要求使得取出的权值和最大。
题目类似一般的DP问题,项最长上升子序列,只不过把上升的要求改成了是前一个的子串,权重也发生了改变 。
判断子串关系,我们用AC 自动机。
我们把AC自动机的fail指针拿出来建立一棵树,然后在求这棵树的dfs序,对于每个点,我所能得到的最大权值一定是该点到root的所有权值。然后我们对每个点的in[x],和out[x]之间的dfs序去更新。
每次取最大值即可
参考代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
using namespace std;
typedef long long LL;
const int maxn=3e5+;
int cnt,root,n,kase,w[+],pos[+];
int INDEX,in[maxn],out[maxn];
char s[maxn];
int fail[maxn];
int S[maxn*],tag[maxn*],MAX,L,R;
int st[maxn],tot;
struct edge {
int v,nxt;
}v[maxn*];
inline void addedge(int x,int y)
{
v[tot]=(edge){y,st[x]};
st[x]=tot++;
}
struct node {
int nxt[],cnt;
}T[maxn];
inline int newnode()
{
cnt++; memset(T[cnt].nxt,,sizeof(T[cnt].nxt));
T[cnt].cnt=; fail[cnt]=;
return cnt;
}
inline void insert(char *s)
{
int now=root; int i=;
while(s[i])
{
if(!T[now].nxt[s[i]-'a'])T[now].nxt[s[i]-'a']=newnode();
now=T[now].nxt[s[i]-'a']; i++;
}
T[now].cnt++;
}
queue<int>Q;
inline void build()
{
Q.push(root);
while(!Q.empty())
{
int k=Q.front(); Q.pop();
if(k!=root)addedge(fail[k],k);
for(int i=;i<;++i)
{
if(!T[k].nxt[i]){T[k].nxt[i]=T[fail[k]].nxt[i];continue;}
if(k!=root)
fail[T[k].nxt[i]]=T[fail[k]].nxt[i];
Q.push(T[k].nxt[i]);
}
}
}
inline void DFS(int u,int fa)
{
in[u]=++INDEX;
for(int i=st[u];~i;i=v[i].nxt)
if(v[i].v!=fa) DFS(v[i].v,u);
out[u]=INDEX;
}
inline void update(int k)
{
S[k]=max(S[k<<],S[k<<|]);
}
inline void down(int k)
{
if(!tag[k])return ;
tag[k<<]=max(tag[k<<],tag[k]);
tag[k<<|]=max(tag[k<<|],tag[k]);
S[k<<]=max(S[k<<],tag[k]);
S[k<<|]=max(S[k<<|],tag[k]); tag[k]=;
}
inline int ask(int l,int r,int k)
{
if(L<=l&&r<=R)return S[k];
int mid=(l+r)>>; down(k);
int res=;
if(L<=mid)res=max(res,ask(l,mid,k<<));
if(R>mid)res=max(res,ask(mid+,r,k<<|)); return res;
}
inline void add(int l,int r,int k)
{
if(L<=l&&r<=R)
{
S[k]=max(S[k],MAX); tag[k]=max(tag[k],MAX);
return ;
}
int mid=(l+r)>>; down(k);
if(L<=mid)add(l,mid,k<<);
if(R>mid)add(mid+,r,k<<|);
update(k);
}
int main()
{
int t; scanf("%d",&t);
while(t--)
{
scanf("%d",&n); cnt=-;
root=newnode(); tot=;
memset(st,-,sizeof(st));
pos[]=;
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();
INDEX=;
DFS(root,-);
int ans=;
memset(S,,sizeof(S));
memset(tag,,sizeof(tag));
for(int i=;i<=n;++i)
{
MAX=; int p=root;
for(int j=pos[i-];j<pos[i];++j)
{
p=T[p].nxt[s[j]-'a']; L=in[p];R=in[p];
int res=ask(,INDEX,);
MAX=max(res,MAX);
}
MAX=MAX+w[i];
ans=max(ans,MAX);
L=in[p];R=out[p];
add(,INDEX,);
}
printf("Case #%d: %d\n",++kase,ans);
}
return ;
}
HDU4117 GRE WORDS(AC自动机+线段树维护fail树的dfs序)的更多相关文章
- hdu 4117 -- GRE Words (AC自动机+线段树)
题目链接 problem Recently George is preparing for the Graduate Record Examinations (GRE for short). Obvi ...
- HDU 5069 Harry And Biological Teacher(AC自动机+线段树)
题意 给定 \(n\) 个字符串,\(m\) 个询问,每次询问 \(a\) 字符串的后缀和 \(b\) 字符串的前缀最多能匹配多长. \(1\leq n,m \leq 10^5\) 思路 多串匹配,考 ...
- 背单词(AC自动机+线段树+dp+dfs序)
G. 背单词 内存限制:256 MiB 时间限制:1000 ms 标准输入输出 题目类型:传统 评测方式:文本比较 题目描述 给定一张包含N个单词的表,每个单词有个价值W.要求从中选出一个子序列使 ...
- hdu 4117 GRE Words AC自动机DP
题目:给出n个串,问最多能够选出多少个串,使得前面串是后面串的子串(按照输入顺序) 分析: 其实这题是这题SPOJ 7758. Growing Strings AC自动机DP的进阶版本,主题思想差不多 ...
- 【AC自动机】【树状数组】【dfs序】洛谷 P2414 [NOI2011]阿狸的打字机 题解
这一题是对AC自动机的充分理解和树dfs序的巧妙运用. 题目背景 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机. 题目描述 打字机上只有28个按键,分别印有26个小写英文字母和' ...
- 【bzoj4771】七彩树 树链的并+STL-set+DFS序+可持久化线段树
题目描述 给定一棵n个点的有根树,编号依次为1到n,其中1号点是根节点.每个节点都被染上了某一种颜色,其中第i个节点的颜色为c[i].如果c[i]=c[j],那么我们认为点i和点j拥有相同的颜色.定义 ...
- hdu 4117 GRE Words (ac自动机 线段树 dp)
参考:http://blog.csdn.net/no__stop/article/details/12287843 此题利用了ac自动机fail树的性质,fail指针建立为树,表示父节点是孩子节点的后 ...
- BZOJ2434:[NOI2011]阿狸的打字机(AC自动机,线段树)
Description 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母. 经阿狸研究发现,这个打字机是这样工作的 ...
- CoderForces 163E e-Government(AC自动机+树状数组维护fail树的dfs序)
E. e-Government time limit per test 1 second memory limit per test 256 megabytes input standard inpu ...
随机推荐
- supervisord进程管理
一:简介 supervisord是一个进程管理工具,提供web页面管理,能对进程进行自动重启等操作. 优点: - 可以将非后台运行程序后台运行 - 自动监控,重启进程 缺点: - 不能管理后台运行程序 ...
- (数据科学学习手札71)在Python中制作个性化词云图
本文对应脚本及数据已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 一.简介 词云图是文本挖掘中用来表征词频的数据可视化 ...
- T-SQL, Part II: IMAGE/TEXT Insert
To insert data to IMAGE/TEXT (both keywords are recommend to replace with nvarbinary(MAX)/nvarchar(M ...
- Ubuntu 16.04.4 安装openjdk各种问题
不知道为什么会如此曲折,一个问题接一个,如果你也遇到问题,可以参考参考 问题1:......has no installation andidate,解决如下(不理解): 参考https://asku ...
- 线程同步&线程池
线程同步&线程池 线程同步 线程不同步会出现的问题: 当多个线程操作同一资源时,会出现重复操作和和操作不存在的资源的问题,为了规避这一问题就需要线程的同步操作来实现资源的共同使用. 线程同步: ...
- ubuntu server 1604 搭建FTP服务器
1.查看是否安装 ftp服务器vsftpd -v 2.安装ftp服务器sudo apt-get install vsftpd 3.如果安装失败或者配置出现问题,可以卸载 ftp服务器sudo apt- ...
- 扛把子组20191031-8 alpha week 1/2 Scrum立会报告+燃尽图 06
此作业的要求参见:https://edu.cnblogs.com/campus/nenu/2019fall/homework/9916 一.小组情况 队名:扛把子 组长:孙晓宇 组员:宋晓丽 梁梦瑶 ...
- Hadoop之HDFS文件系统(二)
HDFS客户端 通过IO流操作HDFS HDFS文件上传 @Test public void putFileToHDFS() throws Exception{ // 1 创建配置信息对象 Confi ...
- 【论文阅读】Where Is My Mirror?
Where Is My Mirror?(ICCV2019收录) 作者: 论文链接: https://arxiv.org/pdf/1908.09101.pdf 1. 研究背景 目前存在的计算机视觉任务 ...
- nvidia gtx1050在kali linux系统下安装显卡驱动,且可以使用x-setting切换显卡
转自:https://www.zzhsec.com/255.html 1.更换源[使用中科大或者官方源都可以] 下面使用中科大的源 root@Andy:/home/dnt# vi /etc/apt/s ...