bzoj3238 差异
思路
观察题目中的式子,可以发现前两项是定值。所以只需要求出最后一项就行了。
然后题目就转化为了求字符串中所有后缀的\(lcp\)长度之和。
可以想到用后缀数组。在后缀数组上两个后缀的\(lcp\)长度表现为两个后缀排名之间的\(height\)的最小值。
所以现在问题就又转化为了在\(height\)数组上求所有区间最小值之和。
这个可以用单调栈做到。
代码
/*
* @Author: wxyww
* @Date: 2019-01-30 19:14:49
* @Last Modified time: 2019-01-30 20:49:38
*/
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<ctime>
#include<bitset>
using namespace std;
typedef long long ll;
#define int ll
const int N = 500010;
ll read() {
ll x=0,f=1;char c=getchar();
while(c<'0'||c>'9') {
if(c=='-') f=-1;
c=getchar();
}
while(c>='0'&&c<='9') {
x=x*10+c-'0';
c=getchar();
}
return x*f;
}
int sa[N],rk[N],height[N],c[N],x[N],y[N];
char s[N];
int m,n;
void get_sa() {
for(int i = 1;i <= m;++i) c[i] = 0;
for(int i = 1;i <= n;++i) ++c[x[i] = s[i]];
for(int i = 2;i <= m;++i) c[i] += c[i - 1];
for(int i = n;i >= 1;--i) sa[c[x[i]]--] = i;
for(int k = 1;k <= n;k <<= 1) {
int num = 0;
for(int i = n - k + 1;i <= n; ++i) y[++num] = i;
for(int i = 1;i <= n;++i) if(sa[i] > k) y[++num] = sa[i] - k;
for(int i = 2;i <= m;++i) c[i] = 0;
for(int i = 1;i <= n;++i) ++c[x[i]];
for(int i = 1;i <= m;++i) c[i] += c[i - 1];
for(int i = n;i >= 1;--i) sa[c[x[y[i]]]--] = y[i];
swap(x,y);
num = 0;
x[sa[1]] = ++num;
for(int i = 2;i <= n;++i) {
if(y[sa[i]] == y[sa[i - 1]] && y[sa[i] + k] == y[sa[i - 1] + k]) x[sa[i]] = num;
else x[sa[i]] = ++num;
}
if(num == n) break;
m = num;
}
}
int h[N],q[N],tail;
void get_height() {
for(int i = 1;i <= n;++i) rk[sa[i]] = i;
int k = 0;
for(int i = 1;i <= n;++i) {
if(rk[i] == 1) continue;
if(k) --k;
int j = sa[rk[i] - 1];
while(j + k <= n && i + k <= n && s[j + k] == s[i + k]) ++k;
h[i] = height[rk[i]] = k;
}
}
ll work() {
int tail = 0;
ll now = 0,ans = 0;
for(int i = 1; i <= n;++i) {
while(height[i] < height[q[tail]] && tail) now -= height[q[tail]] * (q[tail] - q[tail - 1]),tail--;
q[++tail] = i;
now += height[i] * (q[tail] - q[tail - 1]);
ans += now;
}
return ans;
}
int get(int x,int y) {
int ans = 1e9;
int l = min(rk[x],rk[y]),r = max(rk[x],rk[y]);
for(int i = l + 1;i <= r;++i) ans = min(ans,height[i]);
return ans;
}
signed main() {
scanf("%s",s + 1);
n = strlen(s + 1);
m = 'z';
get_sa();
get_height();
ll ans = 0;
for(int i = 1;i <= n;++i)
ans += i * (i - 1) + i * (n - i);
ll LC = 2ll * work();
cout<<ans - LC;
return 0;
}
bzoj3238 差异的更多相关文章
- [bzoj3238]差异(后缀数组+单调栈)
显然我们可以先把len(Ti)+len(Tj)的值先算出来,再把LCP减去.所有len(Ti)+len(Tj)的值为n*(n-1)*(n+1)/2,这个随便在纸上画一画就可以算出来的. 接下来问题就是 ...
- 【BZOJ3238】差异(后缀自动机)
[BZOJ3238]差异(后缀自动机) 题面 BZOJ 题解 前面的东西直接暴力算就行了 其实没必要算的正正好 为了方便的后面的计算 我们不考虑\(i,j\)的顺序问题 也就是先求出\(\sum_{i ...
- 【BZOJ3238】[AHOI2013]差异
[BZOJ3238][AHOI2013]差异 题面 给定字符串\(S\),令\(T_i\)表示以它从第\(i\)个字符开始的后缀.求 \[ \sum_{1\leq i<j\leq n}len(T ...
- 【BZOJ3238】[Ahoi2013]差异 后缀数组+单调栈
[BZOJ3238][Ahoi2013]差异 Description Input 一行,一个字符串S Output 一行,一个整数,表示所求值 Sample Input cacao Sample Ou ...
- bzoj3238 [Ahoi2013]差异 后缀数组+单调栈
[bzoj3238][Ahoi2013]差异 Description Input 一行,一个字符串S Output 一行,一个整数,表示所求值 Sample Input cacao Sample Ou ...
- [bzoj3238][Ahoi2013]差异_后缀数组_单调栈
差异 bzoj-3238 Ahoi-2013 题目大意:求任意两个后缀之间的$LCP$的和. 注释:$1\le length \le 5\cdot 10^5$. 想法: 两个后缀之间的$LCP$和显然 ...
- BZOJ3238 [Ahoi2013]差异 【SAM or SA】
BZOJ3238 [Ahoi2013]差异 给定一个串,问其任意两个后缀的最长公共前缀长度的和 1.又是后缀,又是\(lcp\),很显然直接拿\(SA\)的\(height\)数组搞就好了,配合一下单 ...
- 【BZOJ-3238】差异 后缀数组 + 单调栈
3238: [Ahoi2013]差异 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 1561 Solved: 734[Submit][Status] ...
- 【bzoj3238】 Ahoi2013—差异
http://www.lydsy.com/JudgeOnline/problem.php?id=3238 (题目链接) 题意 给出一个字符串,求${\sum_{1<=i<j<=n} ...
随机推荐
- CLOUD设置过滤方案不共享
1.打开BOS,找到应用框架-动态表单-过滤方案另存 2.找到共享给他人,把可见性全部去掉
- php7函数,声明,返回值等新特性介绍
使用 ... 运算符定义变长参数函数 (PHP 5 >= 5.6.0, PHP 7) 现在可以不依赖 func_get_args(), 使用 ... 运算符 来实现 变长参数函数. functi ...
- python语法糖/装饰器
1.python高阶函数和嵌套函数 1.1高阶函数 def func1(x): return x**2 def func2(x): return x**3 def func(x,y): return ...
- 在IWMS中的分页效果
第一步,你需要在后台修改你所要显示的新闻数目: 第二步,你需要把这段代码加到你需要分页的列表里边 代码: <%=config.TopAd%><asp:Literal id=" ...
- Vue.js文档
参考网址:https://vuefe.cn/ 第一 安装 1.下载到本地后使用<script>标签直接引入 2.使用CDN引入 例如:使用CDN引入 <script src=&qu ...
- java 中的迭代
package cn.zhou.com; import java.util.ArrayList; import java.util.Collection; import java.util.Itera ...
- vue 子组件修改父组件传来的props值,报错
vue不推荐直接在子组件中修改父组件传来的props的值,会报错 [Vue warn]: Avoid mutating a prop directly since the value will be ...
- ng-click 发两次ajax请求的原因及解决方法
http://blog.csdn.net/anmo/article/details/17083125
- python 模块之-shelve
shelve模块比pickle模块简单,只有一个open函数,返回类似字典的对象,可读可写;key必须为字符串,而值可以是python所支持的数据类型 import shelve f = shelve ...
- Appium-desktop安装启用Inspector一直报错An unknown server-side error occurred...
遇到的问题是: 启用Appium-desktop的Inspector一直报错:An unknown server-side error occurred while processing the co ...