题目链接:www.lydsy.com/JudgeOnline/problem.php?id=3238

后缀数组

  这题题面给的暗示性就很强啊……一看就是要用后缀xx一家的算法,由于本蒻只会后缀数组所以就拿后缀数组写了。

  

  这个题目的要求……我们很明显可以直接预处理出来T(i)+T(j)的总和,为n*(n-1)*(n+1)/2。(应该挺容易推的吧?自己画一下(样例):当i为1的时候,j可以为2、3、4、5。则1算了4次,2~5各一次;然后2算三次,3~5算一次;3算两次,4、5算一次;4算一次,5算1次。总共加起来,每个数各算了4次。1~5的和是n*(n+1)/2,总共算了(n-1)次,再乘一下就行了。)

  难点在于LCP的减……这个地方我们可以直接在height数组上搞,我们可以发现,每一对(i,j)都对应了height数组上的一段区间、甚至是点!(当i,j两个子串rank相连的时候)那么同样的,每一个height数组上的一段区间(点)也对应我们要求的一个LCP。

  这样有什么好处呢?原本暴力的做法是枚举i,j,用RMQ算LCP,再减;而现在我们转换成直接算LCP,而不用考虑是谁和谁的LCP(事实上并不会落下任何一个),这样问题就简单多了:利用求LCP的特殊性,我们对于每一个height[i],都能找到一段区间[l,r],使得height[i]=min(height[l]~height[r])。额意思就是 i 是[l,r]这个区间上的最小值。这样LCP=height[i]的对数为 (l-i+1)*(r-i+1) 【ps.我们事先说过,[i,i]这样的一个点也算】也就是说我们的答案里可以减去 2*height[i]*(l-i+1)*(r-i+1) 这样一个值。

  但是!!这样会有重复计算的情况:

    举个栗子:height为 1 2 3 1 2 1 1时,第一个1的[l,r]区间为[1,7],第二个为[1,7],明显有重复计算了([l,i] 和 [i,r]这两段有重叠,也就是计算了两次)所以我们在计算对于每个 i 所能到达的[l,r]区间时,遇到相等元素,必须分开处理:比如如果向右遇到相等元素则可以继续扩展,而向左遇到则停止。(当然你反过来做应该也可以……)

  

  现在分析清楚了,最后的问题是:怎么算l[i],r[i],也就是每个height[i]对应的区间?

  这里我们可以利用一个叫做单调栈的东西,维护栈里的元素height[j]都比当前的height[j]要小,如果大则弹出,这样就能O(N)求出所有的l[i],r[i]了。

错误:1.计算答案的时候,必须要在乘法中加上 (LL)类型强制转换,否则会出错。

   2.在栈为空的时候,意味着左边(右边)所有的元素都比当前的要大,则范围应为从端点(1或n)到i的整个区间,而不是i  (见代码)

 /**************************************************************
Problem: 3238
User: ProgrammingApe
Language: C++
Result: Accepted
Time:3416 ms
Memory:23244 kb
****************************************************************/ //练习六 T1 闫鸿宇
//BZOJ 3238
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define rep(i,n) for(int i=0;i<n;++i)
#define F(i,j,n) for(int i=j;i<=n;++i)
#define D(i,j,n) for(int i=j;i>=n;--i)
using namespace std;
const int N=;
typedef long long LL;
//#define debug
int n,m,sa[N],c[N],wa[N],wb[N],wv[N],rank[N],height[N],l[N],r[N]; int cmp(int *r,int a,int b,int l){
return r[a]==r[b] && r[a+l]==r[b+l];
} void DA(char *s,int *sa,int n,int m){
int i,j,p,*x=wa,*y=wb;
rep(i,m) c[i]=;
rep(i,n) c[x[i]=s[i]]++;
F(i,,m-) c[i]+=c[i-];
D(i,n-,) sa[--c[x[i]]]=i;
for(p=,j=;p<n;j<<=,m=p){
for(p=,i=n-j;i<n;++i) y[p++]=i;
rep(i,n) if (sa[i]>=j) y[p++]=sa[i]-j; rep(i,m) c[i]=;
rep(i,n) c[x[y[i]]]++;
F(i,,m-) c[i]+=c[i-];
D(i,n-,) sa[--c[x[y[i]]]]=y[i];
swap(x,y); p=; x[sa[]]=;
F(i,,n-) x[sa[i]]=cmp(y,sa[i-],sa[i],j) ? p- : p++;
}
} void calheight(char *s,int *sa,int n){
int k=;
F(i,,n) rank[sa[i]]=i;
rep(i,n){
if (k) k--;
int j=sa[rank[i]-];
while(s[i+k]==s[j+k]) k++;
height[rank[i]]=k;
}
} int q[N],st[N],top=;
char s[N];
int main(){
// freopen("input.txt","r",stdin);
// freopen("output.txt","w",stdout);
scanf("%s",&s);
int n=strlen(s);
rep(i,n) s[i]=s[i]-'a'+;
s[n]=; DA(s,sa,n+,);
calheight(s,sa,n);
height[]=height[n+]=; LL ans=(LL)((LL)n*(n-)*(n+))/,delta=;
//T(i) 和 T(j) 的总和 top=;
st[top++]=;
F(i,,n){
while (top && height[st[top-]] > height[i]) top--;
if (top) l[i]=st[top-]+;
else l[i]=;
st[top++]=i;
} top=;
st[top++]=n; r[n]=n;
D(i,n,){
while (top && height[st[top-]] >= height[i]) top--;
if (top) r[i]=st[top-]-;
else r[i]=n;//!!!!
st[top++]=i;
} #ifdef debug
F(i,,n) printf("%d ",height[i]);
printf("\n");
F(i,,n) printf("%d ",l[i]);
printf("\n");
F(i,,n) printf("%d ",r[i]);
printf("\n");
#endif
F(i,,n){
delta+=(LL)*(LL)height[i]*(LL)(i-l[i]+)*(LL)(r[i]-i+);
#ifdef debug
printf("%d * %d * %d = %d\n",height[i],i-l[i]+,r[i]-i+,height[i]*(i-l[i]+)*(r[i]-i+));
#endif
}
#ifdef debug
printf("%lld %lld\n",ans,delta);
#endif
ans-=delta;
printf("%lld\n",ans);
return ;
}

【BZOJ】【3238】【AHOI2013】diff(差异)的更多相关文章

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

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

  2. bzoj 3238 Ahoi2013 差异

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

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

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

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

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

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

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

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

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

  7. ●BZOJ 3238 [Ahoi2013]差异

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

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

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

  9. BZOJ 3238: [Ahoi2013]差异 后缀自动机 树形dp

    http://www.lydsy.com/JudgeOnline/problem.php?id=3238 就算是全局变量,也不要忘记,初始化(吐血). 长得一副lca样,没想到是个树形dp(小丫头还有 ...

  10. BZOJ 3238: [Ahoi2013]差异((单调栈+后缀数组)/(后缀树))

    [传送门[(https://www.lydsy.com/JudgeOnline/problem.php?id=3238) 解题思路 首先原式可以把\(len\)那部分直接算出来,然后通过后缀数组求\( ...

随机推荐

  1. Linux基础知识-文件管理

    Linux目录与路径 cd:切换目录 例如:cd ~willhua,则回到用户willhua的主文件夹  cd ~或者cd,则表示回到自己的的主文件夹  cd -,则表示回到上个目录 pwd:显示目前 ...

  2. LevelDB源码之五Current文件\Manifest文件\版本信息

    版本信息有什么用?先来简要说明三个类的具体用途: Version:代表了某一时刻的数据库版本信息,版本信息的主要内容是当前各个Level的SSTable数据文件列表. VersionSet:维护了一份 ...

  3. 随机获取Mysql数据表的一条或多条记录

    随机获得Mysql数据表的一条或多条记录有很多方法,下面我就以users(userId,userName,password......)表(有一百多万条记录)为例,对比讲解下几个方法效率问题: sel ...

  4. MySQL自用脚本(不定期更新)

    查询指定SQL的trace信息 mysql -uUSER -pPWD -hHOST -e "\ use ins_tc_prd; \ set session optimizer_trace=' ...

  5. 界面控件 - 滚动条ScrollBar

    界面是人机交互的门户,对产品至关重要.在界面开发中只有想不到没有做不到的,有好的想法,当然要尝试着做出来.对滚动条的扩展,现在有很多类是的例子. VS2015的代码编辑是非常强大的,其中有一个功能可以 ...

  6. linux内核设计与实现学习笔记-模块

    模块 1.概念:  如果让LINUX Kernel单独运行在一个保护区域,那么LINUX Kernel就成为了“单内核”.    LINUX Kernel是组件模式的,所谓组件模式是指:LINUX K ...

  7. oracle 11g 表空间使用率

    Oracle数据库表空间使用量查询: select b.file_name 物理文件名,b.tablespace_name 表空间,b.bytes/1024/1024 大小M,(b.bytes-sum ...

  8. JS对文本框值的判断

    JS判断只能是数字和小数点(摘录自其它资料,在此发表只为个人以后使用查找方便) 1.文本框只能输入数字(不包括小数点) <input onkeyup="this.value=this. ...

  9. hdu 2680 Choose the best route

    题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=2680 Choose the best route Description One day , Kiki ...

  10. base64和图片的互转(HTML5的File实现)

    <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="C ...