[AHOI2013]差异 后缀自动机_Parent树
题中要求:
$\sum_{1\leqslant i < j \leq n } Len(T_{i}) +Len(T_{j})-2LCP(T_{i},T_{j})$
公式左边的部分很好求,是一个常量,关键在于如何求取右边的 $2*LCP(T_{i},T_{j})$
在后缀自动机中,任意两个字符串所代表的节点在 $Parent$ 树中的公共祖先所代表的字符串一
定为两个字符串的最长公共后缀,
我们想求最长公共前缀,将字符串倒着插入即可.
一次考虑每个点作为公共祖先能贡献的值:
我们要使答案不重复,不遗漏的计算到. 即任意两个串的 LCP 必须只算一次.
可以一边更新每个点的 right 数组大小,一边计算该点父亲的贡献.
细节可以自己思考.
Code:
- #include <cstdio>
- #include <algorithm>
- #include <cstring>
- #define setIO(s) freopen(s".in","r",stdin)
- #define maxn 1000000
- #define N 30
- #define ll long long
- using namespace std;
- int last=1,tot=1,n;
- int ch[maxn][N],cnt[maxn],f[maxn],dis[maxn],rk[maxn];
- ll C[maxn],ans;
- char str[maxn];
- struct Suffix_Automaton{
- void ins(int c){
- int p=last,np=++tot; last=np; dis[np]=dis[p]+1;
- while(p&&!ch[p][c])ch[p][c]=np,p=f[p];
- if(!p) f[np]=1;
- else{
- int q=ch[p][c],nq;
- if(dis[q]==dis[p]+1) f[np]=q;
- else{
- nq=++tot;
- dis[nq]=dis[p]+1;
- memcpy(ch[nq],ch[q],sizeof(ch[q]));
- f[nq]=f[q],f[q]=f[np]=nq;
- while(p&&ch[p][c]==q) ch[p][c]=nq,p=f[p];
- }
- }
- cnt[last]=1;
- }
- }sam;
- int main(){
- //s//etIO("input");
- scanf("%s",str),n=strlen(str);
- for(int i=n-1;i>=0;--i) sam.ins(str[i]-'a');
- for(int i=1;i<=tot;++i) ++C[dis[i]];
- for(int i=1;i<=tot;++i) C[i]+=C[i-1];
- for(int i=1;i<=tot;++i) rk[C[dis[i]]--]=i;
- for(int i = 1;i <= n; ++i) ans += (long long)i * (n - 1);
- for(int i=tot;i>=1;--i){
- int p=rk[i];
- ans -= (long long)2 * dis[f[p]] * cnt[p] * cnt[f[p]];
- cnt[f[p]]+=cnt[p];
- }
- printf("%lld",ans);
- return 0;
- }
[AHOI2013]差异 后缀自动机_Parent树的更多相关文章
- BZOJ 3238: [Ahoi2013]差异 [后缀自动机]
3238: [Ahoi2013]差异 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 2512 Solved: 1140[Submit][Status ...
- [Ahoi2013]差异(后缀自动机)
/* 前面的那一坨是可以O1计算的 后面那个显然后缀数组单调栈比较好写??? 两个后缀的lcp长度相当于他们在后缀树上的lca的深度 那么我们就能够反向用后缀自动机构造出后缀树然后统计每个点作为lca ...
- 洛谷P4248 [AHOI2013]差异(后缀自动机求lcp之和)
题目见此 题解:首先所有后缀都在最后一个np节点,然后他们都是从1号点出发沿一些字符边到达这个点的,所以下文称1号点为根节点,我们思考一下什么时候会产生lcp,显然是当他们从根节点开始一直跳相同节点的 ...
- BZOJ 3238 [Ahoi2013]差异 ——后缀自动机
后缀自动机的parent树就是反串的后缀树. 所以只需要反向构建出后缀树,就可以乱搞了. #include <cstdio> #include <cstring> #inclu ...
- [bzoj3238][Ahoi2013]差异——后缀自动机
Brief Description Algorithm Design 下面给出后缀自动机的一个性质: 两个子串的最长公共后缀,位于这两个串对应的状态在parent树上的lca状态上.并且最长公共后缀的 ...
- BZOJ 3238: [Ahoi2013]差异 后缀自动机 树形dp
http://www.lydsy.com/JudgeOnline/problem.php?id=3238 就算是全局变量,也不要忘记,初始化(吐血). 长得一副lca样,没想到是个树形dp(小丫头还有 ...
- BZOJ.3238.[AHOI2013]差异(后缀自动机 树形DP/后缀数组 单调栈)
题目链接 \(Description\) \(Solution\) len(Ti)+len(Tj)可以直接算出来,每个小于n的长度会被计算n-1次. \[\sum_{i=1}^n\sum_{j=i+1 ...
- BZOJ3238: [Ahoi2013]差异(后缀自动机)
题意 题目链接 Sol 前面的可以直接算 然后原串翻转过来,这时候变成了求任意两个前缀的最长公共后缀,显然这个值应该是\(len[lca]\),求出\(siz\)乱搞一下 #include<bi ...
- BZOJ3413: 匹配(后缀自动机 线段树合并)
题意 题目链接 Sol 神仙题Orz 后缀自动机 + 线段树合并... 首先可以转化一下模型(想不到qwq):问题可以转化为统计\(B\)中每个前缀在\(A\)中出现的次数.(画一画就出来了) 然后直 ...
随机推荐
- iOS开发 小知识点
1/ iOS汉字百分号互相转换. //汉字 NSString * name = @"时间终于将我对你的爱消耗殆尽"; //汉字转为百分比 NSString * encodeStri ...
- jquery根据滚动条动态加载数据
PHP Code <div id="container"> <?php $query=mysql_query("select * from conten ...
- 为什么叫Unity3d为脚本语言
初接触Unity,看到大家说的都是工作主要是写脚本语言. 一直纳闷为什么说脚本语言呢,c#可不是脚本语言啊. -- -- 后来释然,说它是脚本语言是因为传统程序都是由代码构成的(像iOS.Androi ...
- Python2以及Python3中的除法
前言 在讨论话题之前,我们先说下程序中除法的三种情况: 1. 传统的除法,我称之为整型地板除.在C.C++.Java中常见,特点是整数相除舍弃小数取整,浮点数相除则保留小数(如果有). >> ...
- ZBrush破解版真的好用么?
安装ZBrush®的时候是不是经常出现各种奇葩问题,使用ZBrush时候是不是经常出现停止工作状况,究其原因,原来都是破解搞的鬼.ZBrush破解版你还敢用么? 随着国人对版权的重视,越来越多的制作商 ...
- Python3.7中的常用关键字
本文是在学习Python中遇到的一些关键字,作为日常总结的笔记. Python中有保留字/关键字 保留字就是在Python中预先保留的标识符,这些标识符在Python程序中具有特定用途,不能被程序员作 ...
- 转载:常用 Git 命令清单
转载:常用 Git 命令清单 原文地址:http://www.ruanyifeng.com/blog/2015/12/git-cheat-sheet.html 作者: 阮一峰 我每天使用 Git , ...
- docker images镜像无法删除
删除所有容器: docker rm $(docker ps -aq) 删除镜像: docker rmi $(docker images -q) 如果有镜像无法删除,有可能更改了名字,用docker r ...
- sqrt开平方算法的尝试,是的看了卡马克大叔的代码,我来试试用C#写个0x5f3759df和0x5f375a86跟System.Math.Sqrt到底哪个更强
今天笔试遇到一个代码题,要求写一个开平方算法,回来发现了雷神之锤里的一段神代码: float Q_rsqrt( float number ) { long i; float x2, y; const ...
- 洛谷 P3912 素数个数
P3912 素数个数 题目描述 求1,2,\cdots,N1,2,⋯,N 中素数的个数. 输入输出格式 输入格式: 1 个整数NN. 输出格式: 1 个整数,表示素数的个数. 输入输出样例 输入样例# ...