BZOJ 3238 差异

看这个式子其实就是求任意两个后缀的 $ LCP $ 长度和。前面的 $ len(T_i)+len(T_j) $ 求和其实就是 $ n(n-1)(n+1)/2 $ ,这个是很好推的。。

任意两个后缀的 $ LCP $ 长度和很容易想到构造 height 数组,然后问题就变成了所有区间的最小值的和。

这是个套路题,可以单调栈,但是其实分治也很好写!

设我们要求的区间是 $ [l,r] $ 我们可以找出其中最小值所在的位置,这个可以ST表快速求,然后从这个位置进行分治。

这样的分治每进行一次,总有效的元素数量会减少1,因此复杂度是 $ O(nlogn) $ 的。

开始有个地方漏了 1ll 。。。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
#define MAXN 500006
#define C 130
namespace wtf {
char ch[MAXN];
int sa[MAXN], tp[MAXN], rnk[MAXN], buc[MAXN], len;
int P[MAXN][20], ht[MAXN]; int que(int l, int r) {
int L = (31 - __builtin_clz(r - l + 1));
return (ht[P[l][L]] < ht[P[r - (1 << L) + 1][L]] ? P[l][L] : P[r - (1 << L) + 1][L]);
} void init() {
len = strlen(ch + 1);
int m = C;
for (int i = 1; i <= len; ++i) ++buc[rnk[i] = ch[i]];
for (int i = 1; i <= m; ++i) buc[i] += buc[i - 1];
for (int i = len; i >= 1; --i) sa[buc[rnk[i]]--] = i;
for (int k = 1, p = 0; p < len; k <<= 1) {
p = 0;
for (int i = 0; i <= m; ++i) buc[i] = 0;
for (int i = len - k + 1; i <= len; ++i) tp[++p] = i;
for (int i = 1; i <= len; ++i) if (sa[i] > k) tp[++p] = sa[i] - k;
for (int i = 1; i <= len; ++i) ++buc[rnk[i]];
for (int i = 1; i <= m; ++i) buc[i] += buc[i - 1];
for (int i = len; i >= 1; --i) sa[buc[rnk[tp[i]]]--] = tp[i];
p = 1;
swap(rnk, tp);
rnk[sa[1]] = 1;
for (int i = 2; i <= len; ++i)
rnk[sa[i]] = (tp[sa[i]] == tp[sa[i - 1]] && tp[sa[i] + k] == tp[sa[i - 1] + k]) ? p : ++p;
m = p;
}
for (int i = 1; i <= len; ++i) rnk[sa[i]] = i;
for (int i = 1, k = 0; i <= len; ++i) {
if (k) --k;
while (ch[i + k] == ch[sa[rnk[i] - 1] + k]) ++k;
ht[rnk[i]] = k;
P[i][0] = i;
}
ht[0] = 0x3f3f3f3f;
for (int i = 1; i < 20; ++i)
for (int j = 1; j <= len - (1 << i) + 1; ++j)
P[j][i] = (ht[P[j][i - 1]] < ht[P[j + (1 << i - 1)][i - 1]] ? P[j][i - 1] : P[j + (1 << i - 1)][i - 1]); } long long res = 0; void div(int l, int r) {
if( l > r ) return;
int ps = que( l , r );
res += 1ll * ht[ps] * ( ps - l + 1 ) * ( r - ps + 1 );
div( l , ps - 1 ) , div( ps + 1 , r );
} void main() {
// freopen("1.in","r",stdin);
scanf("%s", ch + 1);
init();
div( 1 , len );
cout << 1ll * ( len - 1 ) * ( len + 1 ) * len / 2 - 2 * res << endl;
}
}
int main() {
wtf::main();
}

BZOJ 3238 差异的更多相关文章

  1. [BZOJ 3238] [AHOI 2013] 差异 【后缀数组 + 单调栈】

    题目链接:BZOJ - 3238 题目分析 显然,这道题就是求任意两个后缀之间的LCP的和,这与后缀数组的联系十分明显. 求出后缀数组后,求出字典序相邻两个后缀的LCP,即 Height 数组. 那么 ...

  2. BZOJ 3238: [Ahoi2013]差异 [后缀数组 单调栈]

    3238: [Ahoi2013]差异 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 2326  Solved: 1054[Submit][Status ...

  3. bzoj 3238 Ahoi2013 差异

    3238: [Ahoi2013]差异 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 2357  Solved: 1067[Submit][Status ...

  4. BZOJ 3238: [Ahoi2013]差异 [后缀自动机]

    3238: [Ahoi2013]差异 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 2512  Solved: 1140[Submit][Status ...

  5. 【BZOJ 3238】 3238: [Ahoi2013]差异(SAM)

    3238: [Ahoi2013]差异 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 3047  Solved: 1375 Description In ...

  6. bzoj 3238: [Ahoi2013]差异 -- 后缀数组

    3238: [Ahoi2013]差异 Time Limit: 20 Sec  Memory Limit: 512 MB Description Input 一行,一个字符串S Output 一行,一个 ...

  7. ●BZOJ 3238 [Ahoi2013]差异

    题链: http://www.lydsy.com/JudgeOnline/problem.php?id=3238 题解: 后缀数组套路深. 问题转化为求出任意两个后缀的LCP之和 在计算贡献时,各种不 ...

  8. 洛谷 P4248: bzoj 3238: [AHOI2013]差异

    题目传送门:洛谷 P4248. 题意简述: 定义两个字符串 \(S\) 和 \(T\) 的差异 \(\operatorname{diff}(S,T)\) 为这两个串的长度之和减去两倍的这两个串的最长公 ...

  9. BZOJ 3238 [Ahoi2013]差异(后缀自动机)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3238 [题目大意] 给出一个串,设T[i]表示从第i位开始的后缀, 求sum(len( ...

随机推荐

  1. c语言中“ld返回值1退回状态”

    在c语言运行中我们经常会看到error:ld return 1 exit status的运行错误,其翻译为"ld返回值1退回状态".在生成程序时.有多个工具参与到步骤的运行中以创建 ...

  2. 【c++ Prime 学习笔记】第1章 开始

    1.1 编写一个简单的程序 int main() { return 0; } 函数 包含4部分: 返回类型(return type) 函数名(function name) 形参列表(parameter ...

  3. [no_code][Alpha]事后分析

    $( "#cnblogs_post_body" ).catalog() 设想和目标 我们的软件要解决什么问题?是否定义得很清楚?是否对典型用户和典型场景有清晰的描述? 我们要解决的 ...

  4. 【二食堂】Alpha - Scrum Meeting 5

    Scrum Meeting 5 例会时间:4.15 12:30 - 13:00 进度情况 组员 昨日进度 今日任务 李健 1. 主页搭建结束issue2. 与后端协商确定接口的设计3. 查找文本区域功 ...

  5. 2021.8.9考试总结[NOIP模拟34]

    T1 Merchant 如果$t=0$时不能达到$s$,那么所拿物品的价值一定关于时间单调递增,答案单调.因此可以特判$0$后二分. 用$sort$复杂度被卡,要用$\textit{nth_eleme ...

  6. C语言零基础入门难发愁,那就快来看看这篇基础整理资料吧

    C语言程序的结构认识 用一个简单的c程序例子,介绍c语言的基本构成.格式.以及良好的书写风格,使小伙伴对c语言有个初步认识. 例1:计算两个整数之和的c程序: #include main() { in ...

  7. Nginx(一):初识Nginx

    一.什么是Nginx? Nginx 是异步框架的Web服务器,也可以用作反向代理.负载平衡器和HTTP缓存.选择Nginx的一些优点:可以高并发连接.内存消耗少.成本低廉.配置文件简单.节省带宽.稳定 ...

  8. Java并发:AbstractQueuedSynchronizer(AQS)

    队列同步器 AbstractQueuedSynchronizer 是一个公共抽象类.提供一个同步器框架,用于实现依赖于先进先出(FIFO)等待队列的阻塞锁和相关同步器(信号量,事件等).使用一个 in ...

  9. vim 常用操作技巧

    记录常用的vim操作技巧,基本满足90%的日常编辑使用. 文档操作 vim test.txt 打开当前目录下的test.txt文档,若不存在则创建该文件 :w 保存当前修改到文件 :w bak.txt ...

  10. 第03课 OpenGL 添加颜色

    添加颜色: 作为第二课的扩展,我将叫你如何使用颜色.你将理解两种着色模式,在下图中,三角形用的是光滑着色,四边形用的是平面着色 上一课中我教给您三角形和四边形的绘制方法.这一课我将教您给三角形和四边形 ...