原题传送门 我用sa做的本题 (码量似乎有点大) 先对原串建sa 考虑如何建图: 从大到小枚举长度len 先将height中等于len的两个位置在并查集合并起来,将lst也合并(lst是链表) 再将长度为len的a串的编号加入所在并查集的lst 然后就珂以查询出每个长度为len的b串所对应a串编号的链表头尾 处理完所有后按加入链表的顺序重新编号 (上面这段见merging函数,语文不好说不清) 现在每个b对应的a的编号都是一段连续的区间 珂以用线段树优化建图 最后跑一下拓扑排序即可得出答案 #i…
好难写的字符串+数据结构问题,写+调了一下午的说 首先理解题意后我们对问题进行转化,对于每个字符串我们用一个点来代表它们,其中\(A\)类串的点权为它们的长度,\(B\)类串的权值为\(0\) 这样我们根据题意把\(A\to B\)的边连起来,同时每个\(B\)类串向所有以其为前缀的\(A\)类串连边 这样我们就得到了一张DAG(如果不是的话就输出\(-1\)),然后对于它拓扑排序之后求权值和最大链即可 但是第二类边该怎么连呢,下面我们来分析一下具体操作 SA转化问题 首先关于这种前后缀相关的问…
这是一道涵盖了字符串.图论.数据结构三个方面的综合大题. 把这道题放在D1T2的人应该拖出去打 前置芝士 首先,您至少要会topsort. 其次,如果您只想拿个暴力分,字符串Hash就足够了:如果您想拿满分,SA和SAM您至少要会一种(本文采用SA). 最后,正解还需要您了解线段树优化建边,并在此基础上用主席树实现. 暴力算法一 对于测试点1~4,暴力建图,Hash优化,可以拿到40分的高分. #include <bits/stdc++.h> #define ll long long #def…
题面 传送门 题解 首先,我们把串反过来,那么前缀就变成后缀,建一个\(SAM\).我们发现一个节点的后缀是它的所有祖先 那么我们是不是直接按着\(parent\)树建边就可以了呢? 显然不是.我们假设在\(SAM\)的某个节点上同时存在某个\(a_i\)和\(b_j\)且\(|b_j|>|a_i|\),\(b_j\)不是\(a_i\)的后缀,但它们仍然有边相连!(自己到自己就当有边吧--) 对于每一个节点,我们把处于这个节点中的所有串排个序,按长度为第一关键字,是否是\(B\)串为第二关键字.…
传送门 思路 设\(dp_i\)表示以\(i\)结尾的\(A\)串,能达到的最长长度. 然后发现这显然可以\(i\)往自己控制的\(k\)连边,\(k\)往能匹配的\(j\)连边,就是个最长路,只要建出图来就完事了. 显然可以用数据结构得到两点之间是否有边,于是就获得了40分的好成绩. 考虑优化这个建图,字符串也就那么几个数据结构,那就后缀树吧. 有了后缀树,可以发现\(k\)会向\(k\)所在的节点的子树连边,注意不包括\(k\)自己的节点. 那么自己节点怎么办呢?把在这里的所有串拆开然后按长…
[BZOJ5496][十二省联考2019]字符串问题(后缀树) 题面 BZOJ 洛谷 题解 首先显然可以把具有支配关系的串从\(A\)到\(B\)连一条有向边,如果\(B_i\)是\(A_j\)的前缀,就从\(B\)连一条边到\(A\).这样子问题就转化成了要求解这个二分图的最长路经,有环答案就是\(-1\). 然后显然就是要找个什么东西出来优化连边是吧... 现在唯一要处理的东西就是要找到个啥玩意,来优化这个满足前缀条件的连边. 假装我们有一个所有后缀都被插进去的\(Trie\)树,那么对于每…
题目链接: [十二省联考2019]字符串问题 首先考虑最暴力的做法就是对于每个$B$串存一下它是哪些$A$串的前缀,然后按每组支配关系连边,做一遍拓扑序DP即可. 但即使忽略判断前缀的时间,光是连边的时间就会爆炸,显然不能暴力连边. 对于前缀不好解决,可以将字符串翻转然后变成判断是否是后缀. 可以发现对于后缀自动机的$parent$树,每个节点是子树内所有节点的后缀. 那么我们可以利用$parent$树来优化建图过程,将树上每个点向子节点连边. 对于每个$A$串和$B$串在后缀自动机上匹配出对应…
ytq鸽鸽出的题真是毒瘤 原题传送门 题目大意: 有一棵有\(n\)个点的树,求有多少方案选\(k\)个联通块使得存在一个中心点\(p\),所有\(k\)个联通块中所有点到\(p\)的距离都\(\leq L\) 我们先从部分分考虑: 算法1 \(2^{nk}\)枚举联通快判断是否可行 期望得分:8pts 代码就不给了 引理1 对于任意一个联通块,可能成为它的中心点的点组成的集合也是一个联通块.正确性显然 推论 这里作为\(k\)个联通块中心点的点组成的集合是一个联通块 算法2 枚举推论中中心点组…
原题传送门 看见一段的异或和不难想到要做异或前缀和\(s\) 我们便将问题转化成:给定\(n\)个数,求异或值最靠前的\(k\)对之和 我们珂以建一个可持久化01trie,这样我们就珂以求出每个值\(s[a]\)与之前所有的值异或值最大的值\(b\)是多少,把这些所有\((b,a)\)塞进一个堆中 每次从堆顶取元素,设这个元素为\((b,a)\),要将\(b\)加入答案,并且在版本\(a\)的01trie中减去\(s[a]\)^\(b\),再取出\(s[a]\)与01trie中的数异或最大值(原…
原题传送门 每个点维护一个堆,表示这个点及其子树所需的每段内存的空间 搜索时从下向上做启发式合并堆中信息,最后根节点堆中所有内存空间之和就是答案 #include <bits/stdc++.h> #define N 200005 #define ll long long #define getchar nc using namespace std; inline char nc(){ static char buf[100000],*p1=buf,*p2=buf; return p1==p2&…