洛谷 P4248 / loj 2377 [AHOI2013] 差异 题解【后缀自动机】【树形DP】
可能是一个 SAM 常用技巧?感觉 SAM 的基础题好多啊..
题目描述
给定一个长度为 \(n\) 的字符串 \(S\) ,令 \(T_i\) 表示它从第 \(i\) 个字符开始的后缀,求:
\[\sum_{1\le i<j\le n}len(T_i)+len(T_j)-2\times lcp(T_i,T_j)
\]其中,\(len(a)\) 表示字符串 \(a\) 的长度,\(lcp(a,b)\) 表示字符串 \(a\) 和字符串 \(b\) 的最长公共前缀。
输入输出格式
输入格式:
一行,一个字符串 \(S\)。
输出格式:
一行,一个整数,表示所求值。
输入输出样例
输入样例:
ababc
输出样例:
54
数据范围与约定
对于 \(100\%\) 的数据,保证 \(2\le n\le 500000\),且均为小写字母。
题解:
这个题的主要考点是 SAM 求 lcp。
lcp 是最长公共前缀,而我们用的是后缀自动机。只需要把字符串翻转过来建立 SAM,得到的就是”前缀自动机“了。
类似后缀自动机的性质,我们建造 parent 树,则父亲总是儿子的前缀。而最简状态自动机上的每个点都有自己的 \(mn,mx\) 表示同一个 Right 集合能表示的最短和最长子串,因此任意两个状态的 lcp 长度就是它们在 parent 树上的最近公共祖先节点的 \(mx\)。
然后我们只需要计算任意两点的 lcp 即可,这个操作可以一次 dfs 搞定。注意统计时子树的根也要算上。
每个点做出的贡献是它的 Right 集合大小,可以通过在 parent 树上统计子树信息得到。
此外,前面的 \(\sum_{1\le i<j\le n}i+j\) 可以推导出来 \(O(n)\) 或 \(O(1)\) 求出来。
时间复杂度 \(O(n)\)。
Code:
#include<cstdio>
#include<cstring>
#include<algorithm>
struct edge
{
int n,nxt;
edge(int n,int nxt)
{
this->n=n;
this->nxt=nxt;
}
edge(){}
}e[1000100];
int head[1000100],ecnt=-1;
void add(int from,int to)
{
e[++ecnt]=edge(to,head[from]);
head[from]=ecnt;
}
int n;
char s[500100];
int ch[26][1000100],mx[1000100],r[1000100],par[1000100],pcnt;
void build()
{
int p=pcnt=1;
for(int i=1;i<=n;++i)
{
int w=s[i]-'a';
int np=++pcnt;
mx[np]=mx[p]+1;
r[np]=1;
while(p&&!ch[w][p])
{
ch[w][p]=np;
p=par[p];
}
if(!p)
par[np]=1;
else
{
int q=ch[w][p];
if(mx[q]==mx[p]+1)
par[np]=q;
else
{
int nq=++pcnt;
mx[nq]=mx[p]+1;
while(p&&ch[w][p]==q)
{
ch[w][p]=nq;
p=par[p];
}
for(int j=0;j<26;++j)
ch[j][nq]=ch[j][q];
par[nq]=par[q];
par[q]=nq;
par[np]=nq;
}
}
p=np;
}
}
long long ans=0;
void dfs(int x)
{
long long tmp=r[x];
for(int i=head[x];~i;i=e[i].nxt)
{
dfs(e[i].n);
ans-=tmp*mx[x]*r[e[i].n]*2;
r[x]+=r[e[i].n];
tmp+=r[e[i].n];
}
}
int main()
{
memset(head,-1,sizeof(head));
scanf("%s",s+1);
n=strlen(s+1);
for(int i=1;i<=n;++i)
ans+=3ll*i*(i-1);
ans>>=1;
std::reverse(s+1,s+1+n);
build();
for(int i=2;i<=pcnt;++i)
add(par[i],i);
dfs(1);
printf("%lld\n",ans);
return 0;
}
洛谷 P4248 / loj 2377 [AHOI2013] 差异 题解【后缀自动机】【树形DP】的更多相关文章
- 洛谷 P4248: bzoj 3238: [AHOI2013]差异
题目传送门:洛谷 P4248. 题意简述: 定义两个字符串 \(S\) 和 \(T\) 的差异 \(\operatorname{diff}(S,T)\) 为这两个串的长度之和减去两倍的这两个串的最长公 ...
- BZOJ_3238_[Ahoi2013]差异_后缀自动机
BZOJ_3238_[Ahoi2013]差异_后缀自动机 Description Input 一行,一个字符串S Output 一行,一个整数,表示所求值 Sample Input cacao Sam ...
- 洛谷 P3975 / loj 2102 [TJOI2015] 弦论 题解【后缀自动机】【拓扑排序】
后缀自动机入门. 题目描述 为了提高智商,ZJY 开始学习弦论. 这一天,她在<String theory>中看到了这样一道问题:对于一个给定的长度为 \(n\) 的字符串,求出它的第 \ ...
- 洛谷AT2046 Namori(思维,基环树,树形DP)
洛谷题目传送门 神仙思维题还是要写点东西才好. 树 每次操作把相邻且同色的点反色,直接这样思考会发现状态有很强的后效性,没办法考虑转移. 因为树是二分图,所以我们转化模型:在树的奇数层的所有点上都有一 ...
- 洛谷P4493 [HAOI2018]字串覆盖(后缀自动机+线段树+倍增)
题面 传送门 题解 字符串就硬是要和数据结构结合在一起么--\(loj\)上\(rk1\)好像码了\(10k\)的样子-- 我们设\(L=r-l+1\) 首先可以发现对于\(T\)串一定是从左到右,能 ...
- BZOJ 3238 [Ahoi2013]差异(后缀自动机)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3238 [题目大意] 给出一个串,设T[i]表示从第i位开始的后缀, 求sum(len( ...
- 洛谷P4770 [NOI2018]你的名字(后缀自动机+线段树)
传送门 我有种自己根本没学过SAM的感觉……最后还是抄了老半天的题解…… 首先,对$S$和每一次的$T$都建一个SAM 先考虑一下$l=1,r=\left| S \right|$的情况 设$lim_i ...
- 【洛谷 P4248】 [AHOI2013]差异(后缀自动机)
题目链接 \[ans=\sum_{1<=i<j<=n}len(T_i)+len(T_j)-2*lcp(T_i,T_j)\] 观察这个式子可以发现,前面两个\(len\)是常数,后面的 ...
- BZOJ3238: [Ahoi2013]差异 (后缀自动机)
Description Input 一行,一个字符串S Output 一行,一个整数,表示所求值 Sample Input cacao Sample Output 54 HINT 2<=N< ...
随机推荐
- 清北学堂 day6 兔子
---恢复内容开始--- [问题描述] 在一片草原上有N个兔子窝,每个窝里住着一只兔子,有M条路径连接这些窝.更特殊地是,至多只有一个兔子窝有3条或更多的路径与它相连,其它的兔子窝只有1条或2条路径与 ...
- cannot find -lf2c
sudo apt-get install libf2c2 auso apt-get install libf2c2-dev
- 斐波那契数列—java实现
最近在面试的时候被问到了斐波那契数列,而且有不同的实现方式,就在这里记录一下. 定义 斐波那契数列指的是这样一个数列 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...
- Cuckoo Hash和多级Hash的粗浅认识
通过对Cuckoo Hash.多级Hash和BloomFilter的粗浅了解,感觉它们三者存在类似之处,算是近亲(暂且把普通的Hash称作远亲). Cuckoo Hash的思想非常简单,冲突时,重Ha ...
- 如何Android中加入扫描名片功能
要想实现android手机通过扫描名片,得到名片信息,可以使用脉可寻提供的第三方SDK,即Maketion ScanCard SDK,脉可寻云名片识别服务.他们的官方网站为http://www.mak ...
- 使用华邦的SPI FLASH作为EPCS时固化NIOS II软件报错及解决方案
Altera器件有EPCS系列配置器件,其实,这些配置器件就是我们平时通用的SPIFlash,据AlteraFAE描述:“EPCS器件也是选用某家公司的SPIFlash,只是中间经过Altera公司的 ...
- hibernate缓存机制(转载)
缓存是介于应用程序和物理数据源之间,其作用是为了降低应用程序对物理数据源访问的频次,从而提高了应用的运行性能.缓存内的数据是对物理数据源中的数据的复制,应用程序在运行时从缓存读写数据,在特定的时刻或事 ...
- CodeForces 907F Power Tower(扩展欧拉定理)
Priests of the Quetzalcoatl cult want to build a tower to represent a power of their god. Tower is u ...
- Linq转换操作之OfType,Cast,AsEnumerable,ToLookup源码分析
Linq转换操作之OfType,Cast,AsEnumerable,ToLookup源码分析 一:Tolookup 1. 从方法的注解上可以看到,ToLookup也是一个k,v的形式,那么问题来了,它 ...
- Intel Galileo development documentation
Intel Galileo development Documentation Author:Liutianchen 1552227, Department of Computer Science,E ...