AHOI2013 差异


方法1:SA

先板个后缀数组(带 \(height\) 不带 \(st\) 表),用单调队列递推每个后缀 \(sa_i\) 对答案的贡献,求和,用定值减之。

#include <bits/stdc++.h>
using namespace std; //Start
typedef long long ll;
typedef double db;
#define mp(a,b) make_pair(a,b)
#define x first
#define y second
#define b(a) a.begin()
#define e(a) a.end()
#define sz(a) int((a).size())
#define pb(a) push_back(a)
const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3f; //Data
const int N=5e5;
int n;
char s[N+7]; //SuffixArray
int m,c[N+7],tp[N+7],rk[N+7],sa[N+7],h[N+7];
void csort(){
for(int i=0;i<=m;i++) c[i]=0;
for(int i=1;i<=n;i++) c[rk[i]]++;
for(int i=1;i<=m;i++) c[i]+=c[i-1];
for(int i=n;i>=1;i--) sa[c[rk[tp[i]]]--]=tp[i];
}
void build(){
for(int i=1;i<=n;i++) rk[i]=s[i],tp[i]=i;
m=128,csort();
for(int w=1,p=1,i;p<n;w<<=1,m=p){
for(p=0,i=n-w+1;i<=n;i++) tp[++p]=i;
for(i=1;i<=n;i++)if(sa[i]>w) tp[++p]=sa[i]-w;
csort(),swap(rk,tp),rk[sa[1]]=p=1;
for(i=2;i<=n;rk[sa[i]]=p,i++)
if(tp[sa[i]]!=tp[sa[i-1]]||tp[sa[i]+w]!=tp[sa[i-1]+w]) p++;
}
for(int i=1,j,k=0;i<=n;h[rk[i++]]=k)
for(k=k?k-1:k,j=sa[rk[i]-1];s[i+k]==s[j+k];k++);
} //Main
int main(){
scanf("%s",&s[1]);
n=strlen(&s[1]),build();
vector<int> q(n+7); int lst=0,qc=0;
vector<ll> f(n+7); ll res=0;
for(int i=1;i<=n;i++){
while(qc&&h[q[qc]]>h[i]) qc--;
int j=qc?q[qc]:lst;
res+=(f[i]=f[j]+1ll*(i-j)*h[i]);
if(!h[i]) lst=i;
else q[++qc]=i;
}
for(int i=1;i<=n;i++)
printf("%d ",sa[i]);puts("");
for(int i=1;i<=n;i++)
printf("%d ",h[i]);puts("");
for(int i=1;i<=n;i++)
printf("%lld ",f[i]);puts("");
printf("%lld\n",1ll*(n-1)*n*(n+1)/2-res*2);
return 0;
}

方法2:SAM

注意到这个式子是 \(\tt SAM\) \(\bf parent~tree\) 树上两点的距离,计算每条边的贡献和即可。

#include <bits/stdc++.h>
using namespace std; //Start
typedef long long ll;
typedef double db;
#define mp(a,b) make_pair(a,b)
#define x first
#define y second
#define b(a) a.begin()
#define e(a) a.end()
#define sz(a) int((a).size())
#define pb(a) push_back(a)
const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3f; //Data
const int N=5e5;
int n;
char s[N+7];
ll ans; //SuffixAutomata
const int T=(N<<1);
int cnt=1,en=1,ch[T+7][26],fa[T+7],dep[T+7],sz[T+7];
int c[T+7],q[T+7];
void insert(int c){
int p=en,np=++cnt;
dep[en=np]=dep[p]+1;
for(;p&&!ch[p][c];p=fa[p]) ch[p][c]=np;
if(!p) fa[np]=1;
else {
int q=ch[p][c];
if(dep[q]==dep[p]+1) fa[np]=q;
else {
int nq=++cnt;
dep[nq]=dep[p]+1;
memcpy(ch[nq],ch[q],sizeof ch[q]);
fa[nq]=fa[q],fa[q]=fa[np]=nq;
for(;ch[p][c]==q;p=fa[p]) ch[p][c]=nq;
}
}
sz[np]=1;
}
void run(){
for(int i=1;i<=cnt;i++) c[i]=0;
for(int i=1;i<=cnt;i++) c[dep[i]]++;
for(int i=1;i<=cnt;i++) c[i]+=c[i-1];
for(int i=1;i<=cnt;i++) q[c[dep[i]]--]=i;
for(int i=cnt;i>=1;i--){
int p=q[i];
sz[fa[p]]+=sz[p];
ans+=1ll*(dep[p]-dep[fa[p]])*sz[p]*(n-sz[p]);
}
} //Main
int main(){
scanf("%s",&s[1]),n=strlen(&s[1]);
for(int i=1;i<=n;i++) insert(s[i]-'a');
run();
printf("%lld\n",ans);
return 0;
}

祝大家学习愉快!

笔记-AHOI2013 差异的更多相关文章

  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]差异_后缀自动机

    BZOJ_3238_[Ahoi2013]差异_后缀自动机 Description Input 一行,一个字符串S Output 一行,一个整数,表示所求值 Sample Input cacao Sam ...

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

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

  6. 【LG4248】[AHOI2013]差异

    [LG4248][AHOI2013]差异 题面 洛谷 题解 后缀数组版做法戳我 我们将原串\(reverse\),根据后缀自动机的性质,两个后缀的\(lcp\)一定是我们在反串后两个前缀的\(lca\ ...

  7. 【BZOJ3238】[AHOI2013]差异

    [BZOJ3238][AHOI2013]差异 题面 给定字符串\(S\),令\(T_i\)表示以它从第\(i\)个字符开始的后缀.求 \[ \sum_{1\leq i<j\leq n}len(T ...

  8. P4248 [AHOI2013]差异 解题报告

    P4248 [AHOI2013]差异 题目描述 给定一个长度为 \(n\) 的字符串 \(S\),令 \(T_i\) 表示它从第 \(i\) 个字符开始的后缀.求 \[\displaystyle \s ...

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

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

随机推荐

  1. c++中的几种函数调用约定(转)

    C++中的函数调用约定(调用惯例)主要针对三个问题: 1.参数传递的方式(是否采用寄存器传递参数.采用哪个寄存器传递参数.参数压桟的顺序等): 参数的传递方式,最常见的是通过栈传递.函数的调用方将参数 ...

  2. Java学习之AWT GUI编程

    Java学习之AWT GUI编程 0x00 前言 既然前面提到了要重写冰蝎和一些反序列化工具,当然就不能随便说说而已.在编写这些工具还是要使用图形化工具来的方便一些,所以提前把GUI的框架给学习一遍. ...

  3. javaScript高级程序设计.pdf && 你不知道的JavaScript

    转: JavaScript高级程序设计 链接:https://pan.baidu.com/s/1iRQ8FjpJqutZJzgdJ8ZBKA 提取码:ndnp 你不知道的JavaScript 链接:h ...

  4. 我要进大厂之大数据MapReduce知识点(2)

    01 我们一起学大数据 今天老刘分享的是MapReduce知识点的第二部分,在第一部分中基本把MapReduce的工作流程讲述清楚了,现在就是对MapReduce零零散散的知识点进行总结,这次的内容大 ...

  5. phpmyadmin 4.8.1任意文件包含(CVE-2018-12613)

    简介 环境复现:https://gitee.com/xiaohua1998/hctf_2018_warmup 考察知识点:文件包含漏洞(phpmyadmin 4.8.1任意文件包含) 线上平台:榆林学 ...

  6. level2行情是什么意思?

    level2行情是由上海证券交易所推出的实时行情信息收费服务产品,主要提供在上海证券交易所上市交易的证券产品的实时交易数据,包括十档行情,买卖队列,逐笔成交,委托总量和加权价格等数据. 投资者根据其功 ...

  7. 如何使用ABBYY FineReader 的用户模式?

    在运用ABBYY FineReader 15(Windows系统)进行文档识别时,用户可能会遇到识别的文档包含一些特殊字符或者其他软件无法识别的字体等情况,容易造成识别出现乱码的结果.在这种情况下,用 ...

  8. 网络拓扑实例之RRPP单环(五)

    组网图形 RRPP简介 在城域网和企业网的网络规划以及实际组网应用中大多会采用环网结构来提高网络的可靠性.采用环网结构的好处是:当环上任意一个节点或节点之间的链路发生故障,都可以将数据流量切换到备份链 ...

  9. C#设计模式-桥接模式(Bridge Pattern)

    引言 例如我有好几个项目,需要外包出去做各种类型的测试,不同的公司基础费用不同,不同的测试类型价格也是不同的.此时不同的项目选择不同的公司和不同类型的测试进行测试价格都是不同的.于是我们可以创建一个项 ...

  10. 【模版 Luogu P3808/P3796/P5357】AC自动机(简论)

    浙江集训Day9,没有出任何实质性成果,只好把昨天打完的板子记一下. 该博客基于luogu的三道模版题.只有一个大致的讲解,主要提供代码给自己参考. ------------------------- ...