Recently George is preparing for the Graduate Record Examinations (GRE for short). Obviously the most important thing is reciting the words.
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.


InputThe 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.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序)的更多相关文章

  1. hdu 4117 -- GRE Words (AC自动机+线段树)

    题目链接 problem Recently George is preparing for the Graduate Record Examinations (GRE for short). Obvi ...

  2. HDU 5069 Harry And Biological Teacher(AC自动机+线段树)

    题意 给定 \(n\) 个字符串,\(m\) 个询问,每次询问 \(a\) 字符串的后缀和 \(b\) 字符串的前缀最多能匹配多长. \(1\leq n,m \leq 10^5\) 思路 多串匹配,考 ...

  3. 背单词(AC自动机+线段树+dp+dfs序)

    G. 背单词 内存限制:256 MiB 时间限制:1000 ms 标准输入输出 题目类型:传统 评测方式:文本比较   题目描述 给定一张包含N个单词的表,每个单词有个价值W.要求从中选出一个子序列使 ...

  4. hdu 4117 GRE Words AC自动机DP

    题目:给出n个串,问最多能够选出多少个串,使得前面串是后面串的子串(按照输入顺序) 分析: 其实这题是这题SPOJ 7758. Growing Strings AC自动机DP的进阶版本,主题思想差不多 ...

  5. 【AC自动机】【树状数组】【dfs序】洛谷 P2414 [NOI2011]阿狸的打字机 题解

        这一题是对AC自动机的充分理解和树dfs序的巧妙运用. 题目背景 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机. 题目描述 打字机上只有28个按键,分别印有26个小写英文字母和' ...

  6. 【bzoj4771】七彩树 树链的并+STL-set+DFS序+可持久化线段树

    题目描述 给定一棵n个点的有根树,编号依次为1到n,其中1号点是根节点.每个节点都被染上了某一种颜色,其中第i个节点的颜色为c[i].如果c[i]=c[j],那么我们认为点i和点j拥有相同的颜色.定义 ...

  7. hdu 4117 GRE Words (ac自动机 线段树 dp)

    参考:http://blog.csdn.net/no__stop/article/details/12287843 此题利用了ac自动机fail树的性质,fail指针建立为树,表示父节点是孩子节点的后 ...

  8. BZOJ2434:[NOI2011]阿狸的打字机(AC自动机,线段树)

    Description 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母. 经阿狸研究发现,这个打字机是这样工作的 ...

  9. 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 ...

随机推荐

  1. Linux软件包管理和磁盘管理实践

    一.自建yum仓库,分别为网络源和本地源 本地yum仓库的搭建就是以下三个步骤: 创建仓库目录结构 上传相应的包到目录下,或者直接挂载光盘也行,如果挂载光盘,第三步就可以省略,因为光盘默认里有repo ...

  2. Hazel,自动整理文件,让你的 Mac 井井有条

    原文地址 https://sspai.com/post/35225 让我们从实际需求出发,看看问题出在哪里,并在此基础上认识和学习使用 Hazel. 电脑随着使用时间的增长,其中的文件也在疯狂的增长, ...

  3. SpingBoot之集成Redis集群

    一.安装Redis集群 安装步骤参照网上教程,Mac安装步骤参照https://github.com/muyl/mac-docker-redis-cluster 二.创建SpringBoot工程 创建 ...

  4. nyoj 76-超级台阶 (递推)

    76-超级台阶 内存限制:64MB 时间限制:1000ms 特判: No 通过数:8 提交数:12 难度:3 题目描述: 有一楼梯共m级,刚开始时你在第一级,若每次只能跨上一级或二级,要走上第m级,共 ...

  5. 简单地迁移你的android jni代码逻辑到iOS - 编写iOS下jni.h的替代 - ocni.h

    1. jni的代码逻辑中与上层平台语言交互了. 2. 使用非Xcode的ide开发工具,希望使用纯净的c/c++代码,不掺杂其它平台相关的语言语法. 3. 只想简单地替换jni代码对上层平台语言的功能 ...

  6. Java——内部类详解

    说起内部类,大家肯定感觉熟悉又陌生,因为一定在很多框架源码中有看到别人使用过,但又感觉自己使用的比较少,今天我就带你具体来看看内部类. 内部类基础 所谓内部类就是在类的内部继续定义其他内部结构类. 在 ...

  7. 【并发编程】Java对并发编程的支持历史

    本博客系列是学习并发编程过程中的记录总结.由于文章比较多,写的时间也比较散,所以我整理了个目录贴(传送门),方便查阅. 并发编程系列博客传送门 本文转载,原文请点击链接 本章主要对Java并发(Con ...

  8. 【集合系列】- 深入浅出的分析 WeakHashMap

    一.摘要 在集合系列的第一章,咱们了解到,Map 的实现类有 HashMap.LinkedHashMap.TreeMap.IdentityHashMap.WeakHashMap.Hashtable.P ...

  9. PostGIS 报错为org.postgresql.util.PSQLException:错误: Operation on mixed SRID geometries

    说明: 在用Openlayers与Geoserver进行开发,做在线编辑功能时,出现一个问题:每当我新增了一根要素后,再次用wfs的方式进行点击查询时,会报错mixed SRID. 通过研究发现在数据 ...

  10. 网站优化之使用Free marker静态化网站文章页

    博客做出来的时候就想要把一些栏目和文章页都静态化处理,当时没啥时间搞,就一直没去弄.但是最近的工作就是做网站,用cms快速搭出了几个网站,cms搭建网站是真的方便啊 如果没有需要二次开发实现的功能,那 ...