3238: [Ahoi2013]差异

Time Limit: 20 Sec  Memory Limit: 512 MB
Submit: 1561  Solved: 734
[Submit][Status][Discuss]

Description

Input

一行,一个字符串S

Output

一行,一个整数,表示所求值

Sample Input

cacao

Sample Output

54

HINT

2<=N<=500000,S由小写英文字母组成

Source

Solution

后缀数组+单调栈

LCP的话,预处理ST表,然后直接求?似乎不好,不过后缀数组的话很好想

肯定是对height做文章...总后缀的长度和很好求..随便一算就出来了...考虑LCP的问题

想法是枚举i,对于每个height[i]前后扩展,找出对答案的贡献,然后最后计算答案..似乎可以,但是WA掉了..

原因是有重复计算,那么要不重复..上述是左右两边扩展,使得区间[l,r]中height[i]为最小,重复的很多,思想还是一样的不过不妨把区间看成[l,r)(PS,其实表述不准确),这样的扩展下去,即向左有限制,向右无限制,向左扩展到相等的就停止,向右遇到相等的可以继续.

那么需要用单调栈去维护扩展的过程..这样就能得到每一个height[i]对答案的贡献了,最后答案需要减掉(i-L[i]+1)*(R[i]-i+1)*(height[i])

注意:

在计算答案的过程中要强制转换.(旧错不再犯)

处理后的单调栈内如果为空,说明可以扩展到开头/结尾(也是看别人的才反应过来的)

PS:正解好像不是这个?...不过POJ上好像做过类似的题,所以写起来还是比较快的..

Code

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define maxn 500010
char S[maxn]; int SA[maxn],len;
int ws[maxn],wv[maxn],wa[maxn],wb[maxn];
int cmp(int *r,int a,int b,int l)
{
return r[a]==r[b]&&r[a+l]==r[b+l];
}
void DA(char *r,int *sa,int n,int m)
{
int p,*x=wa,*y=wb,*t;
for (int i=; i<m; i++) ws[i]=;
for (int i=; i<n; i++) ws[x[i]=r[i]]++;
for (int i=; i<m; i++) ws[i]+=ws[i-];
for (int i=n-; i>=; i--) sa[--ws[x[i]]]=i;
p=; for (int j=; p<n; j*=,m=p)
{
p=; for (int i=n-j; i<n; i++) y[p++]=i;
for (int i=; i<n; i++) if (sa[i]>=j) y[p++]=sa[i]-j;
for (int i=; i<n; i++) wv[i]=x[y[i]];
for (int i=; i<m; i++) ws[i]=;
for (int i=; i<n; i++) ws[wv[i]]++;
for (int i=; i<m; i++) ws[i]+=ws[i-];
for (int i=n-; i>=; i--) sa[--ws[wv[i]]]=y[i];
t=x; x=y; y=t; p=; x[sa[]]=;
for (int i=; i<n; i++)
x[sa[i]]=cmp(y,sa[i-],sa[i],j)?p-:p++;
}
}
int rank[maxn],height[maxn];
void calheight(char *r,int *sa,int n)
{
int k=;
for (int i=; i<=n; i++) rank[sa[i]]=i;
for (int i=; i<n; height[rank[i++]]=k)
{k?k--:;for (int j=sa[rank[i]-]; r[i+k]==r[j+k]; k++);}
}
int stack[maxn],top,L[maxn],R[maxn];
long long tot,lcp;
int main()
{
scanf("%s",S); len=strlen(S); S[len]=;
DA(S,SA,len+,); calheight(S,SA,len);
tot=(long long)((long long)len*(long long)(len-)*(long long)(len+)/);
top=; stack[]=;
for (int i=; i<=len; i++)
{
while (top && height[stack[top-]]>height[i]) top--;
if (top) L[i]=stack[top-]+;
else L[i]=;
stack[top++]=i;
}
top=; stack[]=len;
for (int i=len; i>=; i--)
{
while (top && height[stack[top-]]>=height[i]) top--;
if (top) R[i]=stack[top-]-;
else R[i]=len;
stack[top++]=i;
}
for (int i=; i<=len; i++)
lcp+=(long long)*(long long)(i-L[i]+)*(long long)(R[i]-i+)*(long long)height[i];
printf("%lld\n",tot-lcp);
return ;
}

【BZOJ-3238】差异 后缀数组 + 单调栈的更多相关文章

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

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

  2. 【BZOJ3238】[Ahoi2013]差异 后缀数组+单调栈

    [BZOJ3238][Ahoi2013]差异 Description Input 一行,一个字符串S Output 一行,一个整数,表示所求值 Sample Input cacao Sample Ou ...

  3. [AHOI2013] 差异 - 后缀数组,单调栈

    [AHOI2013] 差异 Description 求 \(\sum {len(T_i) + len(T_j) - 2 lcp(T_i,T_j)}\) 的值 其中 \(T_i (i = 1,2,... ...

  4. bzoj3238 [Ahoi2013]差异 后缀数组+单调栈

    [bzoj3238][Ahoi2013]差异 Description Input 一行,一个字符串S Output 一行,一个整数,表示所求值 Sample Input cacao Sample Ou ...

  5. BZOJ_3238_[Ahoi2013]差异_后缀数组+单调栈

    BZOJ_3238_[Ahoi2013]差异_后缀数组+单调栈 Description Input 一行,一个字符串S Output 一行,一个整数,表示所求值 Sample Input cacao ...

  6. BZOJ.4199.[NOI2015]品酒大会(后缀数组 单调栈)

    BZOJ 洛谷 后缀自动机做法. 洛谷上SAM比SA慢...BZOJ SAM却能快近一倍... 显然只需要考虑极长的相同子串的贡献,然后求后缀和/后缀\(\max\)就可以了. 对于相同子串,我们能想 ...

  7. BZOJ3238 [Ahoi2013]差异 【后缀数组 + 单调栈】

    题目链接 BZOJ3238 题解 简单题 经典后缀数组 + 单调栈套路,求所有后缀\(lcp\) #include<iostream> #include<cstdio> #in ...

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

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

  9. BZOJ_3879_SvT_后缀数组+单调栈

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

随机推荐

  1. 【转】LiveWriter插入高亮代码插件介绍 基于SyntaxHighighter

    转自:http://www.cnblogs.com/yaoshiyou/archive/2009/11/25/1610901.html 插件介绍 辛苦了两人小时写日志不小心浏览器崩溃了,发誓以后一定记 ...

  2. ES6 .Set数据结构去除重复元素

    用法一 var set = new Set([1, 2, 3, 4, 2, 8, 4]); //两个2 for (var elem of set) { console.log(elem) // 输出结 ...

  3. mvc webapi 返回字符串自动加双引号

    来自:http://www.cnblogs.com/David-Huang/p/4351023.html 返回字符串,突然碰到双引号号问题,幸亏有人解决了. 返回XMLDocument类型,默认会解析 ...

  4. 清北学堂2017NOIP冬令营入学测试P4749 F’s problem(f)

    时间: 1000ms / 空间: 655360KiB / Java类名: Main 背景 冬令营入学测试 描述 这个故事是关于小F的,它有一个怎么样的故事呢. 小F是一个田径爱好者,这天它们城市里正在 ...

  5. python 图

    class Graph(object): def __init__(self,*args,**kwargs): self.node_neighbors = {} self.visited = {} d ...

  6. 金山快盘+TortoiseSVN构建版本控制仓库

    金山会盘+TortoiseSVN构建版本控制仓库 之前写过一篇文章介绍 如何利用花生壳和VisualSVN Server建立远程代码仓库,具体请参照: <如何利用花生壳和VisualSVN Se ...

  7. 走进 Spring IOC 的世界

    转载出自:http://blog.csdn.net/m13666368773/article/details/7802126 1. IoC理论的背景我们都知道,在采用面向对象方法设计的软件系统中,它的 ...

  8. DOM之parentNode与offsetParent

    DOM中有两个属性parentNode和offsetParent,想必区别大家都是知道的,可用法上还是有一些需要注意的地方,尤其是后者,想知道吗?继续往下看咯. parentNode指的是父节点,el ...

  9. 如何在Vue2中实现组件props双向绑定

    Vue学习笔记-3 前言 Vue 2.x相比较Vue 1.x而言,升级变化除了实现了Virtual-Dom以外,给使用者最大不适就是移除的组件的props的双向绑定功能. 以往在Vue1.x中利用pr ...

  10. TAR命令详解

    上图,VPN截图,画蛇添足! 在Linux中,压缩与解压用得最多的tar.tar命令确实很厉害. tar -c: 建立压缩档案-x:解压-t:查看内容-r:向压缩归档文件末尾追加文件-u:更新原压缩包 ...