首先说一下,对一个刚学Trie树的蒟蒻来说(就是我),这道题是一道好题。Trie树比较简单,所以就不详细写了。

Rima

内存限制:256 MiB

时间限制:1000 ms

标准输入输出

题目类型:传统

评测方式:文本比较

上传者: cqbzgm

题目描述

Adrian对单词押韵很感兴趣。如果两个单词的最长公共后缀的长度与两个单词中较长那个的长度一样,或者等于较长单词的长度减一,则这两个单词押韵。换句话说,如果A,B的最长公共后缀LCS(A,B)≥max(|A|,|B|)-1,则A和B押韵。

有一天,在阅读一套短篇小说时,他决定创造出能够使每两个相邻单词押韵的最长的单词序列,序列中的每个单词只能出现一次。但是Adrian已经厌倦了这个任务,所以他决定回去读小说,并要求你代替他解决这个任务。

输入格式

第一行输入包含整数N(1≤N≤5*1e5)。表示单词的个数。

接下来N行每行包含一个只由小写英文字母组成的字符串。表示可以用于组成序列的单词。数据保证每个单词都是不同的,保证所有单词的长度之和不超过3*1e6。

输出格式

输出一个整数。表示单词序列的最长长度。

样例

样例输入1

4

honi

toni

oni

ovi

样例输出1

3

样例输入2

5

ask

psk

krafna

sk

k

样例输出2

4

样例输入3

5

pas

kompas

stas

s

nemarime

样例输出3

1

数据范围与提示

对于30%的数据,N≤18。

首先这道题要用到的是最长公共后缀,所以可以倒着将字符串插入字典树中以方便操作。那么我们便将样例1插入字典树中:



我们可以发现,在Tri树中,具有“押韵”关系的两个点,它们的"end"节点必定是父子或者是兄弟关系,没有例外。(比如oni和honi的end节点就是父子关系,honi和toni就是兄弟关系。)

答案已经很明显了。现在要考虑的是方法。

在考场中,我用的方法是从树的叶节点开始搜索,统计出连通的end节点的数量(这里连通的定义是具有父子关系或兄弟关系)。这样做没有问题,也很好想,但它是错的。如果我们直接暴力统计的,我们会忽略一些特殊情况(虽然这样可以骗至少40分)

这组数据:

7
ab
aab
ccb
cb
bbb
bb
b

如果使用刚才我说的直接统计每个节点在它的子树中end节点的数量(这个节点不一定是end节点,因为这样还包括两个end节点是兄弟的情况),那么它就会输出7,而正确答案却是6。

造成答案错误的原因是我们忽略了题目中的一个限制条件。在这个队列中,只有“相邻”的两个单词押韵才符合答案。



在1节点中,我们直接统计了红点的个数7个。但我们无论如何都无法将"ab","aab","ccb","cb","bbb","bb","b"这7个单词排在一起。原因是因为“b”旁边只能排有2个单词

我们可以按"aab" "ab" "b" "bb" "bbb"的顺序排列我们可以在"ab"和"b"之间插入一个"cb",这样就变成了"aab" "ab" "cb" "b" "bb" "bbb"。但"ccb"却怎么也插不进去了。

让我们回到Tri树中。使用\(f_{u}\)数组来表示一个单词它后面(注意是后面,这意味着这个单词只能接一边。而不能将其它单词接到它的前面。)的最多能接上单词的数量。

关于它的状态转移方程 :

\(f_{u}=max(f_{v}) +sum\) (\(sum\)表示u的子节点中除了f值最大的一个v节点外其它合法子节点的数量(合法意味着这个节点是end节点))

但f数组却不是最终的答案。注意我们对它的定义是在它的后面,也就是只能接上一边,所以状态转移方程不是\(f_{u}=max1(f_{v1}) +max2(f_{v2})+sum\)

(\(max1\) 和\(max2\)是第一大和第二大)

在每个节点中,定义\(ans=max1(f_{v1}) +max2(f_{v2})+sum\),答案就是最大的\(ans\).

(你们直接看代码吧,我自己也解释不清)

#include <iostream>
#include <string>
#include <cstdio>
#include <map>
#include <cstring>
using namespace std; #define N 500010
#define M 3000010
#define LL long long string A;
int n,p[M][30],k=1,ans,f[M];
bool IsEnd[M]; void Insert(string A) {
int now=1;
for(int i=A.length()-1;i>=0;i--) {
if(!p[now][A[i]-'a'])
p[now][A[i]-'a']=++k;
now=p[now][A[i]-'a'];
}
IsEnd[now]=1;
} void dfs(int x) {
int sum=0;
pair<int,int> maxx;
maxx=make_pair(0,0);
for(int i=0,v;i<26;i++)
if(p[x][i]) {
v=p[x][i];
if(IsEnd[v]) sum++;
dfs(v);
maxx=max(maxx,make_pair(maxx.first,f[v]));//这里不用pair也行,但我用其他方法
maxx=max(maxx,make_pair(f[v],maxx.first));//就WA了,所以吹爆pair
f[x]=max(f[x],f[v]);
}
if(IsEnd[x]) f[x]+=max(1,sum);
else f[x]=0;
ans=max(ans,IsEnd[x]+maxx.first+maxx.second+max(0,sum-2));
} int main() {
cin>>n;
for(int i=1;i<=n;i++) {
cin>>A;
Insert(A);
}
dfs(1);
cout<<ans;
}

校内模拟赛 : Rima —— 字典树+树形DP的更多相关文章

  1. 5.4 省选模拟赛 修改 线段树优化dp 线段树上二分

    LINK:修改 题面就不放了 大致说一下做法.不愧是dls出的题 以前没见过这种类型的 不过还是自己dp的时候写丑了. 从这道题中得到一个结论 dp方程要写的优美一点 不过写的过丑 优化都优化不了. ...

  2. codehunter 「Adera 6」杯省选模拟赛 网络升级 【树形dp】

    直接抄ppt好了--来自lyd 注意只用对根判断是否哟留下儿子 #include<iostream> #include<cstdio> using namespace std; ...

  3. 【BZOJ-2286】消耗战 虚树 + 树形DP

    2286: [Sdoi2011消耗战 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 2120  Solved: 752[Submit][Status] ...

  4. 51nod 1353 树 | 树形DP经典题!

    51nod 1353 树 | 树形DP好题! 题面 切断一棵树的任意条边,这棵树会变成一棵森林. 现要求森林中每棵树的节点个数不小于k,求有多少种切法. 数据范围:\(n \le 2000\). 题解 ...

  5. 【BZOJ-3572】世界树 虚树 + 树形DP

    3572: [Hnoi2014]世界树 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 1084  Solved: 611[Submit][Status ...

  6. bzoj 2286(虚树+树形dp) 虚树模板

    树链求并又不会写,学了一发虚树,再也不虚啦~ 2286: [Sdoi2011]消耗战 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 5002  Sol ...

  7. 洛谷 P1453 城市环路 ( 基环树树形dp )

    题目链接 题目背景 一座城市,往往会被人们划分为几个区域,例如住宅区.商业区.工业区等等.B市就被分为了以下的两个区域--城市中心和城市郊区.在着这两个区域的中间是一条围绕B市的环路,环路之内便是B市 ...

  8. BZOJ_2286_[Sdoi2011]消耗战_虚树+树形DP+树剖lca

    BZOJ_2286_[Sdoi2011]消耗战_虚树+树形DP Description 在一场战争中,战场由n个岛屿和n-1个桥梁组成,保证每两个岛屿间有且仅有一条路径可达.现在,我军已经侦查到敌军的 ...

  9. [10.12模拟赛] 老大 (二分/树的直径/树形dp)

    [10.12模拟赛] 老大 题目描述 因为 OB 今年拿下 4 块金牌,学校赞助扩建劳模办公室为劳模办公室群,为了体现 OI 的特色,办公室群被设计成了树形(n 个点 n − 1 条边的无向连通图), ...

随机推荐

  1. 本地启oracle实例服务无法重启,协议适配器错误

    今天遇到一位朋友的oracle实例服务无法起来,启动时报错: 分析的原因是可能早上服务器突然断电造成的,经过对tns的测试 经过我们讨论和诊断,最后诊断的处理方法是将实例删了重装,处理后服务恢复正常: ...

  2. Django 数据库多字段同时关联一个表为外键的解决办法

    多个字段对应一个外键时,会报错,如: class Storehouse_list(models.Model):#库位列表 nid = models.AutoField(primary_key=True ...

  3. Codeforces - 1198D - Rectangle Painting 1 - dp

    https://codeforces.com/contest/1198/problem/D 原来是dp的思路,而且是每次切成两半向下递归.好像在哪里见过类似的,貌似是紫书的样子. 再想想好像就很显然的 ...

  4. python pickle模块的用法

    pickle用于python特有的类型,和python的数据类型间进行转换,提供四个功能 dumps,dump,loads,load. pickle 的用法 #pickle.dumps 将数据通过特殊 ...

  5. Windows平台网站图片服务器架构的演进

    在主流的Web站点中,图片往往是不可或缺的页面元素,尤其在大型网站中,几乎都将面临“海量图片资源”的存储.访问等相关技术问题.在针对图片服务器的架构扩展中,也会历经很多曲折甚至是血泪教训(尤其是早期规 ...

  6. python 数据分析 Numpy(Numerical Python Basic)

    a = np.random.random((2,4)) a Out[5]: array([[0.20974732, 0.73822026, 0.82760722, 0.050551 ], [0.773 ...

  7. HDU-3810 超大容量01背包

    题意:有n堆野兽,每堆野兽屠杀完完需要花费ti时间,可以增加金钱gi,敌法师有瞬移技能,可以从某堆野兽移到另一堆野兽,题目有给定从哪堆可以移到哪堆.最后问在满足打的金钱多余m的情况下的最少时间.数据范 ...

  8. ltp-ddt eth_parallel_processing

    ETH_S_FUNC_PARALLEL_PROCESSING: source 'common.sh'; prepare_nfs_mount.sh "/mnt/nfs_mount"| ...

  9. Java EE的优越性主要表现在哪些方面

    J2 EE的优越性主要表现在哪些方面 J2EE基于JAVA 技术,与平台无关. J2EE拥有开放标准,许多大型公司实现了对该规范支持的应用服务器.如BEA ,IBM,ORACLE等. J2EE提供相当 ...

  10. No Spring Session store is configured: set the 'spring.session.store-type'

    发现session store type使用来存放session的存储方式,目前Spring boot中只支持Redis方式. 由于本应用暂无需将session放入redis的需求,故这里就可以将se ...