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. IP网段的判断

    一.    OSI七层模型 表示 说明 作用 应用层 HTTP.ftp 协议 表示层 UTF-8 将应用层协议翻译成计算机可识别的语言 会话层 管理传输层 传输层 TCP/UDP 建立以及断开连接 网 ...

  2. 私有git搭建

    Git简介(目前世界上最先进的分布式版本控制系统) 那什么是版本控制系统? 你可以把一个版本控制系统(缩写VCS)理解为一个特殊的“数据库”,在需要的时候,它可以帮你完整地保存一个项目的快照.当你需要 ...

  3. C++中对C的扩展学习新增语法——内联函数以及函数参数

    内联函数以及函数参数 内联函数 使用 inline 关键字必须和函数体放在一起. 内联函数具有内部链接属性. 内联函数会被编译器在编译阶段替换到函数调用的地方. 可以把内联函数定义写到头文件中,多个c ...

  4. [LC]111题 二叉树的最小深度 (递归)

    ①题目 给定一个二叉树,找出其最小深度. 最小深度是从根节点到最近叶子节点的最短路径上的节点数量. 说明: 叶子节点是指没有子节点的节点. 示例: 给定二叉树 [3,9,20,null,null,15 ...

  5. hdu 1556 Color the ball (树状数组)

    Color the ballTime Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Tot ...

  6. 接口测试之-postman

    在使用postman进行接口测试的时候,对于有些接口字段需要时间戳加密,这个时候我们就遇到2个问题,其一是接口中的时间戳如何得到?其二就是对于现在常用的md5加密操作如何在postman中使用代码实现 ...

  7. .NET进阶篇06-async异步、thread多线程3

    知识需要不断积累.总结和沉淀,思考和写作是成长的催化剂 梯子 一.任务Task1.启动任务2.阻塞延续3.任务层次结构4.枚举参数5.任务取消6.任务结果7.异常二.并行Parallel1.Paral ...

  8. PostGIS 结合Openlayers以及Geoserver实现最短路径分析(二)

    前文讲述了怎么用ArcMap制作了测试数据,并导入了PostGIS,接下来我们需要结合PgRouting插件,对入库的数据再进行一下处理. 1.在pgAdmin中,执行下面的sql语句 --添加起点字 ...

  9. PostGIS mysql_fdw安装(Linux)

    ##本人在安装过程中,可能因为系统环境因素或是其他原因,参考网上的文章没有一篇是非常顺利的,所以自己总结一下. ##安装过程中非常坎坷,有些地方反复了好几次,弄的有点模糊,但模糊的地方在文中我会指出. ...

  10. Maven入门【小白千万别点进】

    曾经有个女孩问我为什么要学Maven,我吧唧嘴就怼:Maven项目没有jar包它不香嘛,照样运行它不香嘛?如果让我一句话形容Maven,我会这样形容:"妈妈再也不用担心小明拿U盘去小红电脑里 ...