链接



解题思路:很明显前面∑1<=i<j<=nlen(Ti)+len(Tj)\sum_{1<=i<j<=n}len(T_i)+len(T_j)∑1<=i<j<=n​len(Ti​)+len(Tj​)是定值len∗(len+1)∗(len−1)/2len*(len+1)*(len-1)/2len∗(len+1)∗(len−1)/2
那么题目就是变成了求任意两个后缀的lcp求和
根据后缀数组的求法lcp(suf(i),suf(j))=min(Height[rk[i]+1],....,Height[rk[j]]);lcp(suf(i),suf(j))=min(Height[rk[i]+1],....,Height[rk[j]]);lcp(suf(i),suf(j))=min(Height[rk[i]+1],....,Height[rk[j]]);


我们先举个例子:假设某个字符串的Height数组=0 1 3 2 0 0 2
最暴力的做法就是我们枚举for(inti=1;i<=n;++i)for(int i = 1; i <= n; ++ i)for(inti=1;i<=n;++i)
再枚举for(intj=i+1;j<=n;++j)for(int j = i + 1;j<=n;++j)for(intj=i+1;j<=n;++j)

每一列的看实际是一个单调栈2进来把3挤出去,我们只是模拟一下过程就好了,还有一个细节是看第3列的2出现了两次,因为上一轮3被2覆盖了


#include <iostream>
#include <cstdio>
#include <stack>
#include <sstream>
#include <limits.h>
#include <vector>
#include <map>
#include <cstring>
#include <deque>
#include <cmath>
#include <iomanip>
#include <unordered_map>
#include <queue>
#include <algorithm>
#include <set>
#define mid ((l + r) >> 1)
#define Lson rt << 1, l , mid
#define Rson rt << 1|1, mid + 1, r
#define ms(a,al) memset(a,al,sizeof(a))
#define log2(a) log(a)/log(2)
#define _for(i,a,b) for( int i = (a); i < (b); ++i)
#define _rep(i,a,b) for( int i = (a); i <= (b); ++i)
#define for_(i,a,b) for( int i = (a); i >= (b); -- i)
#define rep_(i,a,b) for( int i = (a); i > (b); -- i)
#define lowbit(x) ((-x) & x)
#define IOS std::ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define INF 0x3f3f3f3f
#define LLF 0x3f3f3f3f3f3f3f3f
#define hash Hash
#define next Next
#define pb push_back
#define f first
#define s second
using namespace std;
const int N = 2e6 + 10, mod = 1e9 + 9;
const int maxn = 500010;
const long double eps = 1e-5;
const int EPS = 500 * 500;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> PII;
typedef pair<ll,ll> PLL;
typedef pair<double,double> PDD;
template<typename T> void read(T &x)
{x = 0;char ch = getchar();ll f = 1;while(!isdigit(ch)){if(ch == '-')f*=-1;ch=getchar();}while(isdigit(ch)){x = x*10+ch-48;ch=getchar();}x*=f;
}
template<typename T, typename... Args> void read(T &first, Args& ... args)
{read(first);read(args...);
}
//......................
// sa[l]排序是lth的后缀的开始位置
//ra[l]是起点是l的后缀排名多少
//lcp(suf(i),suf(j)) = min(H(ra[i] + 1),....H(ra[j]));
//区间最小值倍增求
// H(i)是rk[i]和re[i-1]的lcp
//这个板子下标是从0开始,rank从1开始
struct SA {int sa[maxn], ra[maxn], height[maxn];int t1[maxn], t2[maxn], c[maxn];void build(int *str, int n, int m) {str[n] = 0;n++;int i, j, p, *x = t1, *y = t2;for (i = 0; i < m; i++) c[i] = 0;//排序的桶for (i = 0; i < n; i++) c[x[i] = str[i]]++;for (i = 1; i < m; i++) c[i] += c[i - 1];for (i = n - 1; i >= 0; i--) sa[--c[x[i]]] = i;for (j = 1; j <= n; j <<= 1) {//所有长度为1,2,4,8....的子串的排序//长度够长的话就是所有的后缀排序p = 0;for (i = n - j; i < n; i++) y[p++] = i;for (i = 0; i < n; i++) if (sa[i] >= j) y[p++] = sa[i] - j;for (i = 0; i < m; i++) c[i] = 0;for (i = 0; i < n; i++) c[x[y[i]]]++;for (i = 1; i < m; i++) c[i] += c[i - 1];for (i = n - 1; i >= 0; i--) sa[--c[x[y[i]]]] = y[i];swap(x, y);p = 1;x[sa[0]] = 0;for (i = 1; i < n; i++)x[sa[i]] = (y[sa[i - 1]] == y[sa[i]] && y[sa[i - 1] + j] == y[sa[i] + j]) ? p - 1 : p++;if (p >= n) break;m = p;}n--;for (int i = 0; i <= n; i++) ra[sa[i]] = i;for (int i = 0, j = 0, k = 0; i <= n; i++) {if (k) k--;j = sa[ra[i] - 1];while (str[i + k] == str[j + k]) k++;height[ra[i]] = k;}st_init(height, n);}int lg[maxn], table[23][maxn];void st_init(int *arr, int n) {if (!lg[0]) {lg[0] = -1;for (int i = 1; i < maxn; i++)lg[i] = lg[i / 2] + 1;}for (int i = 1; i <= n; ++i)table[0][i] = arr[i];for (int i = 1; i <= lg[n]; ++i)for (int j = 1; j <= n; ++j)if (j + (1 << i) - 1 <= n)table[i][j] = min(table[i - 1][j], table[i - 1][j + (1 << (i - 1))]);//从j开始长度是2^i次方得st表}int lcp(int l, int r) {l = ra[l], r = ra[r];if (l > r) swap(l, r);++l;int t = lg[r - l + 1];//区间长度return min(table[t][l], table[t][r - (1 << t) + 1]);}
} sa;
int Per, m;
int a[600200];
char s[600200];
ll ans = 0;
int main()
{scanf("%s",s);int len = strlen(s);for(int i = 0; i < len; ++ i) a[i] = (int)s[i];sa.build(a,len,255);ans += 1ll * len * (len + 1) * (len - 1) / 2;ll sum = 0;for(int i = 1; i <= len; ++ i){ll tmp = 1;while(sa.height[i] < a[Per - 1] && Per >= 1) sum -= a[Per - 1], Per --, tmp ++;sum += sa.height[i] * tmp;while(tmp --)a[Per ++] = sa.height[i];ans -= 2 * sum;}cout << ans << endl;return 0;
}

[Ahoi2013]差异[后缀数组+单调栈]相关推荐

  1. [BZOJ3238][AHOI2013]差异 [后缀数组+单调栈]

    题目地址 - GO-> 题目大意: 给定一个长度为 nn 的字符串SS,令TiTi表示它从第ii个字符开始的后缀,求以下这个式子的值: ∑1≤i<j≤nlen(Ti)+len(Tj)−2× ...

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

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

  3. bzoj 3238: [Ahoi2013]差异(后缀数组+单调栈)

    3238: [Ahoi2013]差异 Time Limit: 20 Sec  Memory Limit: 512 MB Submit: 3443  Solved: 1562 [Submit][Stat ...

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

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

  5. [bzoj3238]差异(后缀数组+单调栈)

    显然我们可以先把len(Ti)+len(Tj)的值先算出来,再把LCP减去.所有len(Ti)+len(Tj)的值为n*(n-1)*(n+1)/2,这个随便在纸上画一画就可以算出来的. 接下来问题就是 ...

  6. 【BZOJ3238】差异,后缀数组+单调栈维护height

    Time:2016.05.23 Author:xiaoyimi 转载注明出处谢谢 传送门 思路: 题意已经说的很明白了. 关键在于如何快速求得各lcp的和 有一个重要的性质 排名为i和j(i<j ...

  7. BZOJ3879: SvT【后缀数组+单调栈】

    Description (我并不想告诉你题目名字是什么鬼) 有一个长度为n的仅包含小写字母的字符串S,下标范围为[1,n]. 现在有若干组询问,对于每一个询问,我们给出若干个后缀(以其在S中出现的起始 ...

  8. POJ - 3415 Common Substrings(后缀数组+单调栈)

    题目链接:点击查看 题目大意:给出两个字符串,再给出一个k,问两个字符串中长度大于等于k的公共子串有多少个(种类可重复) 题目分析:因为涉及到了子串问题,先用后缀数组跑出height数组来,接下来如果 ...

  9. 【BZOJ3879】SvT,后缀数组+单调栈维护sum

    Time:2016.08.15 Author:xiaoyimi 转载注明出处谢谢 如果有不明白的地方可以在下面评论问我 传送门 思路: 建立后缀数组求出Height 如果说对每次询问暴力求LCP累加的 ...

最新文章

  1. 深入理解 C 指针阅读笔记 -- 第三章
  2. 从七个方面,面试大厂高级工程师
  3. PostgreSQL 最佳实践 - 水平分库(基于plproxy)
  4. 自增主键与UUID的优缺点
  5. 20款免费公司企业wordpress主题
  6. matlab e52pt,matlab 神经网络的文字识别 有详细注释-补充样本
  7. 在成长中遇到的挫折事件对你的影响_孩子一遇到困难就退缩?3个方法培养孩子逆商,提升抗挫折能力...
  8. 你知道手动探针台系统的用途及组成部分吗?
  9. OpenGL ES 3.1 Android扩展包介绍
  10. 文件系统FatFsR0.09a翻译(三):ff.h
  11. Erlang之ETS,DETS入门
  12. winXP和win2003双系统下启动NTDETECT错误解决方法
  13. 明日书苑|硬笔书法临写指南
  14. Cocos2d-x 学习笔记(11.1) MoveBy MoveTo
  15. C++ 汇编代码分析——递归函数调用、浮点数比较、选择语句
  16. 1024是什么节日 (中国程序员节)
  17. Python 在 excel 中画 饼状图 折线图
  18. 计算机械结构变形,机械结构温度变化的位移计算.ppt
  19. 数字化转型再下一城,数字孪生厂商优锘科技宣布完成超3亿元融资
  20. 计算机教育专业的专业任选课,什么叫自由选修课 又什么叫全校任选课

热门文章

  1. PanoNet3D:一个基于激光雷达点云语义和几何理解的3D目标检测方法
  2. 使用Numpy实现PCA
  3. GitHub代码一键转VS Code:只需+1s
  4. ORDNet:为场景分割捕获全范围依赖关系
  5. mysql5.6.20二进制安装
  6. PHP问题 —— Deprecated: Function ereg_replace() is de
  7. nginx telnet sshd
  8. nagios不能 发送飞信报警一例
  9. sar分辨率公式_初识合成孔径雷达SAR
  10. Python网络爬虫笔记:下载、分析京东P20销售数据