洛谷 P4248: bzoj 3238: [AHOI2013]差异
题目传送门:洛谷 P4248。
题意简述:
定义两个字符串 \(S\) 和 \(T\) 的差异 \(\operatorname{diff}(S,T)\) 为这两个串的长度之和减去两倍的这两个串的最长公共前缀的长度。
给定一个字符串,定义从第 \(i\) 个字符开始的后缀为 \(Suf_i\)。
求 \(\sum_{1\le i<j\le n}\operatorname{diff}(Suf_i,Suf_j)\)。
题解:
化简式子,原式等于
\[\begin{align*}&\left(\sum_{1\le i<j\le n}i+j\right)-2\times\sum_{1\le i<j\le n}\operatorname{lcp}(Suf_i,Suf_j)\\=& \frac{n(n-1)(n+1)}{2}-2\times\sum_{1\le i<j\le n}\operatorname{lcp}(Suf_i,Suf_j)\end{align*}\]
所以只要求出后半部分即可。
建立字符串的后缀数组。
考虑 Height 数组的贡献:Height 数组中 [2, n] 内的每一个区间都给答案贡献区间最小值。
套路:每个区间的区间最小值之和,使用单调栈解决。
#include <cstdio>
#include <cstring> typedef long long LL;
const int MN = ; int N;
char str[MN]; int M;
int rk[MN], rk2[MN], SA[MN], SA2[MN];
int buk[MN], cnt;
int Height[MN]; void GetHeight() {
int k = ;
for (int i = ; i <= N; ++i) {
if (rk[i] == ) { k = Height[] = ; continue; }
if (k) --k;
int j = SA[rk[i] - ];
while (i + k <= N && j + k <= N && str[i + k] == str[j + k]) ++k;
Height[rk[i]] = k;
}
} void Rsort() {
for (int i = ; i <= M; ++i) buk[i] = ;
for (int i = ; i <= N; ++i) ++buk[rk[i]];
for (int i = ; i <= M; ++i) buk[i] += buk[i - ];
for (int i = N; i >= ; --i) SA[buk[rk[SA2[i]]]--] = SA2[i];
} void GetSA() {
M = ;
for (int i = ; i <= N; ++i) rk[i] = str[i] - 'a' + , SA2[i] = i;
Rsort();
for (int j = ; j < N; j <<= ) {
int P = ;
for (int i = N - j + ; i <= N; ++i) SA2[++P] = i;
for (int i = ; i <= N; ++i) if (SA[i] > j) SA2[++P] = SA[i] - j;
Rsort();
rk2[SA[]] = P = ;
for (int i = ; i <= N; ++i) {
if (rk[SA[i]] != rk[SA[i - ]] || rk[SA[i] + j] != rk[SA[i - ] + j]) ++P;
rk2[SA[i]] = P;
}
for (int i = ; i <= N; ++i) rk[i] = rk2[i];
M = P;
if (M == N) break;
}
GetHeight();
} int st[MN], t;
int L[MN], R[MN]; int main() {
scanf("%s", str + );
N = strlen(str + );
GetSA();
st[t = ] = ;
for (int i = ; i <= N; ++i) {
while (t && Height[st[t]] > Height[i]) R[st[t--]] = i;
L[i] = st[t];
st[++t] = i;
} while (t) R[st[t--]] = N + ;
LL Ans = (LL)(N - ) * N * (N + ) / ;
for (int i = ; i <= N; ++i)
Ans -= 2ll * (R[i] - i) * (i - L[i]) * Height[i];
printf("%lld\n", Ans);
return ;
}
洛谷 P4248: bzoj 3238: [AHOI2013]差异的更多相关文章
- 洛谷 P4248 / loj 2377 [AHOI2013] 差异 题解【后缀自动机】【树形DP】
可能是一个 SAM 常用技巧?感觉 SAM 的基础题好多啊.. 题目描述 给定一个长度为 \(n\) 的字符串 \(S\) ,令 \(T_i\) 表示它从第 \(i\) 个字符开始的后缀,求: \[ ...
- BZOJ 3238: [Ahoi2013]差异 [后缀数组 单调栈]
3238: [Ahoi2013]差异 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 2326 Solved: 1054[Submit][Status ...
- bzoj 3238 Ahoi2013 差异
3238: [Ahoi2013]差异 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 2357 Solved: 1067[Submit][Status ...
- BZOJ 3238: [Ahoi2013]差异 [后缀自动机]
3238: [Ahoi2013]差异 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 2512 Solved: 1140[Submit][Status ...
- bzoj 3238: [Ahoi2013]差异 -- 后缀数组
3238: [Ahoi2013]差异 Time Limit: 20 Sec Memory Limit: 512 MB Description Input 一行,一个字符串S Output 一行,一个 ...
- ●BZOJ 3238 [Ahoi2013]差异
题链: http://www.lydsy.com/JudgeOnline/problem.php?id=3238 题解: 后缀数组套路深. 问题转化为求出任意两个后缀的LCP之和 在计算贡献时,各种不 ...
- BZOJ 3238 [Ahoi2013]差异(后缀自动机)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3238 [题目大意] 给出一个串,设T[i]表示从第i位开始的后缀, 求sum(len( ...
- BZOJ 3238: [Ahoi2013]差异 后缀自动机 树形dp
http://www.lydsy.com/JudgeOnline/problem.php?id=3238 就算是全局变量,也不要忘记,初始化(吐血). 长得一副lca样,没想到是个树形dp(小丫头还有 ...
- BZOJ 3238: [Ahoi2013]差异((单调栈+后缀数组)/(后缀树))
[传送门[(https://www.lydsy.com/JudgeOnline/problem.php?id=3238) 解题思路 首先原式可以把\(len\)那部分直接算出来,然后通过后缀数组求\( ...
随机推荐
- Java中split的对象被特殊字符(.或|)分隔
在Java中,一个String对象被一些特殊字符分隔时,可以使用split()方法,生成一个String[],然后进行其他的操作,就像下面这样: String str = "a1_b1_c1 ...
- There is no getter for property named 'notice' in 'class com.game.domain.Notices'
在插入数据时报错:There is no getter for property named 'notice' in 'class com.game.domain.Notices' 四月 11, 20 ...
- BZOJ5120 无限之环(费用流)
方案合法相当于要求接口之间配对,黑白染色一波,考虑网络流.有一个很奇怪的限制是不能旋转直线型水管,考虑非直线型水管有什么特殊性,可以发现其接口都是连续的.那么对于旋转水管,可以看做是把顺/逆时针方向上 ...
- 【BZOJ1835】基站选址(线段树)
[BZOJ1835]基站选址(线段树) 题面 BZOJ 题解 考虑一个比较暴力的\(dp\) 设\(f[i][j]\)表示建了\(i\)个基站,最后一个的位置是\(j\)的最小代价 考虑如何转移\(f ...
- 3532: [Sdoi2014]Lis 最小字典序最小割
3532: [Sdoi2014]Lis Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 865 Solved: 311[Submit][Status] ...
- 2017 3 8 练习赛 t3 路径规划
题目大意是让你在一棵树上找到一条路径使得(路径边权和*路径最小值) 最大. 这道题有两种方法. 1.点分治,考虑过重心的每条路径是否可能成为答案,枚举从根出发的每一条路径中的最小值等于总路径的最小值, ...
- python之旅:三元表达式、列表推导式、生成器表达式、函数递归、匿名函数、内置函数
三元表达式 #以下是比较大小,并返回值 def max2(x,y): if x > y: return x else: return y res=max2(10,11) print(res) # ...
- Linux crontab 命令格式与举例
每五分钟执行 */5 * * * * 每小时执行 0 * * * * 每天执行 0 0 * * * 每周执行 0 0 * * 0 每月执行 0 0 1 ...
- OCR论文整理
论文地址:https://github.com/ChanChiChoi/awesome-ocr 下面是已经看过的论文: CTPN CRNN TextBoxes EAST FOTS PixelLink
- POI上传,导入excel文件到服务器1
首先说一下所使用的POI版本3.8,需要用的的Jar包: dom4j-1.6.1.jarpoi-3.8-20120326.jarpoi-ooxml-3.8-20120326.jarpoi-ooxml- ...