bzoj3238】的更多相关文章

[BZOJ3238]差异(后缀自动机) 题面 BZOJ 题解 前面的东西直接暴力算就行了 其实没必要算的正正好 为了方便的后面的计算 我们不考虑\(i,j\)的顺序问题 也就是先求出\(\sum_{i=1}^n\sum_{j=1}^n[i\neq j]len[i]\) 然后对于每个后缀树上的节点,减去一下贡献 也就是\(size[i]*(size[i]-1)*(len[i]-len[i.parent])\) 这样的话,就很容易计算了.. 我知道我写的一点都不清楚 构建出\(SAM\)后,\(pa…
[BZOJ3238][AHOI2013]差异 题面 给定字符串\(S\),令\(T_i\)表示以它从第\(i\)个字符开始的后缀.求 \[ \sum_{1\leq i<j\leq n}len(T_i)+len(T_j)-2*lcp(T_i,T_j) \] 其中\(len(a)\)表示串\(a\)的长度,\(lcp(a,b)\)表示串\(a,b\)的最长公共前缀 题解 把这个式子看作两边分开求: Part1: \[ \sum_{1\leq i<j\leq n}len(T_i)+len(T_j)\…
http://www.lydsy.com/JudgeOnline/problem.php?id=3238 (题目链接) 题意 给出一个字符串,求${\sum_{1<=i<j<=n}  len(T_i)+len(T_j)-2*lcp(T_i,T_j)}$,其中${T_i}$表示i的后缀 Solution 很简单,求个后缀数组,然后单调栈扫一遍就可以了. 细节 开LL 代码 // bzoj3238 #include<algorithm> #include<iostream&…
[BZOJ3238][Ahoi2013]差异 Description Input 一行,一个字符串S Output 一行,一个整数,表示所求值 Sample Input cacao Sample Output 54 HINT 2<=N<=500000,S由小写英文字母组成 题解:先跑后缀数组得到height数组,然后我们为了得到∑LCP(i,j),可以转变成求每个height数组对答案做了多少贡献(也就是有多少对LCP(i,j)=height[i]). 根据height数组的定义,两个后缀的L…
求和式的前两项可以直接算,问题是对于每对i,j计算LCP. 一个比较显然的性质是,LCP(i,j)是h[rk[i]+1~rk[j]]中的最小值. 从h的每个元素角度考虑,就是对每个h计算有多少对i,j以它为最小值. 在h中使用单调栈统计左右比它小的第一个元素,相乘得到结果. #include<cstdio> #include<cstring> #include<algorithm> #define rep(i,l,r) for (int i=(l); i<=(r)…
Description 先分析一下题目,我们显然可以直接算出sigma(len[Ti]+len[Tj])的值=(n-1)*n*(n+1)/2 接着就要去算这个字符串中所有后缀的两两最长公共前缀总和 首先可以想到后缀数组,我们计算好后缀数组之后再进行对height数组的计算 对于以x,y开头的后缀,它们的最长公共前缀为min(height[sa[i]])(rank[x]<=i<=rank[y]) 但从以往习惯的height数组入手我们发现并没有办法解决这个问题 不如换个角度思考,我们可以枚举这个…
题目传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3238 这道题从大概半年以前就开始啃了,不过当时因为一些细节没调出来,看了Sakits神犇的博客之后也没明白自己挂在哪里,于是就抄了个题解.然后现在突然想到填这个坑(其实是为了复习一下后缀数组模板),换了种思路才过了这道题……然而还是不知道当时那种写法为什么错……似乎是挂在判重? 解法(Accepted): 首先我们可以观察一下这个式子(见下),我们可以把它拆开,变成sigma(len(…
题目链接 BZOJ3238 题解 简单题 经典后缀数组 + 单调栈套路,求所有后缀\(lcp\) #include<iostream> #include<cstdio> #include<cmath> #include<map> #include<cstring> #include<algorithm> #define LL long long int #define Redge(u) for (int k = h[u],to; k;…
[bzoj3238][Ahoi2013]差异 Description Input 一行,一个字符串S Output 一行,一个整数,表示所求值 Sample Input cacao Sample Output 54 题解: 任意两个字符串的lcp是什么,就是如 a,b  那么若a==b 那么为len(a) 否则设sa[a]<sa[b] 那么为min(height[sa[a]+1-------sa[b]]) #include<cstring> #include<iostream>…
差异 bzoj-3238 Ahoi-2013 题目大意:求任意两个后缀之间的$LCP$的和. 注释:$1\le length \le 5\cdot 10^5$. 想法: 两个后缀之间的$LCP$和显然不好求. 我们先构建后缀数组. 那么任意两个后缀之间的$LCP$之和就是所有$sa$数组上所有区间的$ht$最小值. 换言之,我们有一个$a$数组. 显然让你求所有区间的权值和. 一个区间的权值为这个区间内所有$a_i$的最小值. 这个过程我们可以用单调栈实现. Code: #include <io…
题意: 思路:显然len(t[i])+len(t[j])这部分的和是一定的 那么问题就在于如何快速求出两两之间lcp之和 考虑将它们排名后用SA可以很方便的求出lcp,且对答案没有影响,因为形式都是数对 所以用SA求出height 每个位置的height作为lcp的区间为扩展到最左最右,直到height[x]<height[i],height[y]<height[i] 这样合法的左区间为[x+1,i],右区间为[i,y-1] 考虑如何维护一个支持寻找最靠近当前位置的比当前位置上的数小的位置 这…
BZOJ3238 [Ahoi2013]差异 给定一个串,问其任意两个后缀的最长公共前缀长度的和 1.又是后缀,又是\(lcp\),很显然直接拿\(SA\)的\(height\)数组搞就好了,配合一下单调栈 //#pragma GCC optimize("O3") //#pragma comment(linker, "/STACK:1024000000,1024000000") #include<bits/stdc++.h> using namespace…
3238: [Ahoi2013]差异 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 1561  Solved: 734[Submit][Status][Discuss] Description Input 一行,一个字符串S Output 一行,一个整数,表示所求值 Sample Input cacao Sample Output 54 HINT 2<=N<=500000,S由小写英文字母组成 Source Solution 后缀数组+单调栈…
Description Input 一行,一个字符串S Output 一行,一个整数,表示所求值 Sample Input cacao Sample Output 54 HINT 2<=N<=500000,S由小写英文字母组成 YY了后缀自动机的解法: 首先题意就是让你求sigma(LCP(i,j)|i<j) 将字符串反过来,考虑两个后缀对答案的贡献,其实就是节点x和y的lca节点包含的最长子串长度 那么将SAM构出来,考虑当LCA为节点z时,有多少满足条件的(x,y),这个枚举z的相邻…
首先把后缀数组和height数组都搞出来... 然后用两个单调栈维护$[l, r]$表示对于一个点$x$,满足$height[x] \le height[l..x] \ \&\&\  height[x] < height[x..r]$的最小的$l$和最大的$r$ 这样子就可以保证不会重复计算了 /************************************************************** Problem: 3238 User: rausen Langu…
都LCP了很显然是要用到后缀数组的 显然前面的那个东西是可以直接算出来的 关键在于LCP的和怎么快速的计算 不难想到穷举height[i],然后判断这个height[i]可能成为多少对后缀的LCP 考虑到LCP(i,j)=min(height[rank[i]+1~rank[j]]) 假定rank[i]<rank[j]; 假设height[l]是左边第一个小于height[i]的,height[r]是右边第一个小于height[i]的 则height[i]是(i-l)(r-i)对后缀的LCP 但这…
题目链接 思路 观察题目中的式子,可以发现前两项是定值.所以只需要求出最后一项就行了. 然后题目就转化为了求字符串中所有后缀的\(lcp\)长度之和. 可以想到用后缀数组.在后缀数组上两个后缀的\(lcp\)长度表现为两个后缀排名之间的\(height\)的最小值. 所以现在问题就又转化为了在\(height\)数组上求所有区间最小值之和. 这个可以用单调栈做到. 代码 /* * @Author: wxyww * @Date: 2019-01-30 19:14:49 * @Last Modifi…
https://www.lydsy.com/JudgeOnline/problem.php?id=3238 跟 bzoj3879 差不多 #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define N 500001 int n,m,mm; char s[N]; int a[N]; int v[N]; ,k; ][N…
sam好,好写好调好ac! 原题: 图片题面好评 2<=N<=500000 在syq大神的指点下终于理解一道后缀自动姬了quq (其实是因为这道题的dp主要是在后缀树(就是拓扑序)上搞树形dp…… 恩sam有个好玩的东西呢就是搞出后缀自动姬后根据max搞一个类似与后缀数组中countrank的东西 这个就是自动姬的拓扑序,同时也是parent树的不知道什么序,反正如果倒叙遍历这个序列的话x一定会比father[x]先访问到就对了 然后就可以直接用countrank搞树形dp辣 每个树点对答案的…
传送门 后缀自动机好题. 题意: 做法:samsamsam 废话 考虑翻转字串,这样后缀的最长公共前缀等于前缀的最长公共后缀. 然后想到parentparentparent树上面两个串的最长公共后缀跟他们所处状态的lcalcalca有关系. 于是对于每一个lcalcalca都处理出它的sizesizesize和maxlengthmax_{length}maxlength​就行了. 代码: #include<bits/stdc++.h> #define ri register int using…
传送门 BZOJ 洛谷 Solution SA版本的 考虑可以建一个SAM? 那么接下来我们就考虑每一对点对之间的贡献了. 把这个式子化简一下就是无序点对之间的那啥(自己意会一下) 然后我们定义边权为len的差值. 然后那个东西不就是\(i->j\)的路径吗? 然后就可以分开考虑每一条边的贡献了. 然后就没有然后了. 代码实现 代码戳这里…
题意 题目链接 Sol 前面的可以直接算 然后原串翻转过来,这时候变成了求任意两个前缀的最长公共后缀,显然这个值应该是\(len[lca]\),求出\(siz\)乱搞一下 #include<bits/stdc++.h> #define int long long #define LL long long using namespace std; const int MAXN = 1e6 + 10; LL N; char a[MAXN]; int fa[MAXN], len[MAXN], siz…
显然我们可以先把len(Ti)+len(Tj)的值先算出来,再把LCP减去.所有len(Ti)+len(Tj)的值为n*(n-1)*(n+1)/2,这个随便在纸上画一画就可以算出来的. 接下来问题就是如何把LCP减去.我们先用后缀数组把height求出来,当有一段区间l~r,height[i]为height[l]~height[r]中的最小值,那么随便取rk[l]~rk[r]中的两个后缀,他们的LCP则都是height[i],这个很好理解吧.那么l~r这个区间里有(l-i+1)*(r-i+1)对…
题面 戳这里 题解 考虑把要求的那个东西拆开算,前面一个东西像想怎么算怎么算,后面那个东西在建出\(height\)数组后相当于是求所有区间\(min\)的和*2,单调栈维护一波即可. #include<bits/stdc++.h> #define For(i,x,y) for (int i=(x);i<=(y);i++) #define Dow(i,x,y) for (int i=(x);i>=(y);i--) #define cross(i,k) for (int i=firs…
题意 分析 这个题目还是很优秀的.sigma(len(Ti)+len(Tj))的值是一定的=n*(n+1)*(n-1)/2.那么关键就是求任意两个后缀的lcp的和了. 我们怎么求两个后缀的lcp?如果用后缀自动机的话,我们可以先把字符串反过来,然后建后缀自动机,那么两个后缀的lcp就是他们两个在parent树上的最近公共祖先(lca)的len.我们要求的是任意两个后缀的lcp的和,我们可以考虑在parent上跑树形dp.令dp[u]为以u为lca的lcp的和. #include <cstdio>…
Description Input 一行,一个字符串S Output 一行,一个整数,表示所求值 Sample Input cacao Sample Output 54 HINT 2<=N<=500000,S由小写英文字母组成 Solution 后缀自动机的fa指针反向以后可以形成一个树结构,称作Parent树一个节点的father是他的最长后缀,那么很显然任意两个子串的最长公共后缀位于它们Parent树对应节点的lca处为了利用这个性质,可以把串反过来建立SAM,问题转化成对这个串的所有前缀…
https://www.lydsy.com/JudgeOnline/problem.php?id=3238 https://www.luogu.org/problemnew/show/P4248 参考:https://blog.csdn.net/Vmurder/article/details/42721101 第一道接触后缀树的题,然而不想讲这个东西. 我们只需要知道将串倒着建后缀自动机parent树就是后缀树即可. 然后两个后缀的lcp就是他们的lca的len. 设点u,则过点u的后缀就有su…
Brief Description Algorithm Design 下面给出后缀自动机的一个性质: 两个子串的最长公共后缀,位于这两个串对应的状态在parent树上的lca状态上.并且最长公共后缀的长度就是lca状态的len. 证明:对于一个串,他的所有祖先节点都是他的后缀,并且深度越大,长度越长,由此不难说明两个子串的最长公共后缀一定在lca状态上.考察这个lca,他代表的所有子串一定都是两个子串的公共后缀,我们直接取最大的就可以了. 有了这个性质,我们就可以开始乱搞了. Code #inc…
求一个字符串的∑ ∑ len[i] + len[j] - 2 * lcp(i, j),其中i,j表示从i,j开始的后缀. 方法一:SA+单调栈,自行yy. 方法二:SAM构造出来,然后每个状态对答案的贡献就是:C(|right_s|,2)*(Max_s-Max_parent_s).前面使用的变量名含义与CLJ论文里的一致.right集合的大小需要构造后缀树然后从那些叶子节点开始算. 由于可以用马拉车在O(N)时间内枚举所有的回文串,所以在parent树中倍增找到每个回文串的出现次数即可. 跑得巨…
Description Input 一行,一个字符串S Output 一行.一个整数.表示所求值 Sample Input cacao Sample Output 54 HINT 2<=N<=500000,S由小写英文字母组成 后缀自己主动机的性质: 5.两个串的最长公共后缀,位于这两个串相应状态在Parent树上的近期公共祖先状态. 那么我们把原题里后缀的最长公共前缀反过来,把原串反过来建SAM就变成了最长公共后缀 然后题意就是求一个串全部前缀的最长公共后缀长度之和 我们能够在parent树…