【BZOJ4566】找相同字符(后缀数组)
【BZOJ4566】找相同字符(后缀数组)
题面
题解
后缀数组的做法,应该不是很难想
首先看到两个不同的串,当然是接在一起求\(SA,height\)
那么,考虑一下暴力
在两个串各枚举一个后缀,他们的\(lcp\)就是对答案产生的贡献
现在优化一下,按照\(SA\)的顺序枚举来处理\(lcp\)
利用一个单调栈维护一下,每次记录一下前面有多少个的贡献和当前答案一样就好啦
只是有点难写。。。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define MAX 440000
#define ll long long
int n,gr[MAX];
int SA[MAX],hg[MAX],rk[MAX];
int a[MAX],t[MAX],x[MAX],y[MAX];
bool cmp(int i,int j,int k){return y[i]==y[j]&&y[i+k]==y[j+k];}
void GetSA()
{
int m=50;
for(int i=1;i<=n;++i)t[x[i]=a[i]]++;
for(int i=1;i<=m;++i)t[i]+=t[i-1];
for(int i=n;i>=1;--i)SA[t[x[i]]--]=i;
for(int k=1;k<=n;k<<=1)
{
int p=0;
for(int i=1;i<=n;++i)y[i]=0;
for(int i=n-k+1;i<=n;++i)y[++p]=i;
for(int i=1;i<=n;++i)if(SA[i]>k)y[++p]=SA[i]-k;
for(int i=0;i<=m;++i)t[i]=0;
for(int i=1;i<=n;++i)t[x[y[i]]]++;
for(int i=1;i<=m;++i)t[i]+=t[i-1];
for(int i=n;i>=1;--i)SA[t[x[y[i]]]--]=y[i];
swap(x,y);
x[SA[1]]=p=1;
for(int i=2;i<=n;++i)x[SA[i]]=cmp(SA[i],SA[i-1],k)?p:++p;
if(p>=n)break;
m=p;
}
for(int i=1;i<=n;++i)rk[SA[i]]=i;
for(int i=1,j=0;i<=n;++i)
{
if(j)--j;
while(a[i+j]==a[SA[rk[i]-1]+j])++j;
hg[rk[i]]=j;
}
}
int Q1[MAX],top1,S1[MAX];
int Q2[MAX],top2,S2[MAX];
ll ans,sum1,sum2;
char ch[MAX];
int main()
{
scanf("%s",ch+1);
for(int i=1,l=strlen(ch+1);i<=l;++i)a[++n]=ch[i]-96,gr[n]=1;
a[++n]=27;
scanf("%s",ch+1);
for(int i=1,l=strlen(ch+1);i<=l;++i)a[++n]=ch[i]-96,gr[n]=2;
GetSA();
for(int i=1,tot=0;i<n;++i)
{
ans+=(gr[SA[i]]==1)?sum2:sum1;
ll tmp1=0;
while(top1&&Q1[top1]>=hg[i+1])
{
tmp1+=S1[top1];
sum1-=1ll*(Q1[top1]-hg[i+1])*S1[top1];
--top1;
}
++top1;S1[top1]=tmp1;Q1[top1]=hg[i+1];
ll tmp2=0;
while(top2&&Q2[top2]>=hg[i+1])
{
tmp2+=S2[top2];
sum2-=1ll*(Q2[top2]-hg[i+1])*S2[top2];
--top2;
}
++top2;S2[top2]=tmp2;Q2[top2]=hg[i+1];
if(gr[SA[i]]==1)++S1[top1],sum1+=hg[i+1];
else ++S2[top2],sum2+=hg[i+1];
}
printf("%lld\n",ans);
return 0;
}
【BZOJ4566】找相同字符(后缀数组)的更多相关文章
- 【BZOJ4566】[Haoi2016]找相同字符 后缀数组+单调栈
[BZOJ4566][Haoi2016]找相同字符 Description 给定两个字符串,求出在两个字符串中各取出一个子串使得这两个子串相同的方案数.两个方案不同当且仅当这两 个子串中有一个位置不同 ...
- [HAOI2016] 找相同字符 - 后缀数组,单调栈
[HAOI2016] 找相同字符 Description 给定两个字符串,求出在两个字符串中各取出一个子串使得这两个子串相同的方案数.两个方案不同当且仅当这两个子串中有一个位置不同. \(n,m \l ...
- BZOJ.4566.[HAOI2016]找相同字符(后缀数组 单调栈)
题目链接 给定两个字符串,求它们有多少个相同子串.相同串的位置不同算多个. POJ3145简化版. 后缀自动机做法见这儿,又快又好写(一下就看出差距了..) //13712kb 4076ms #inc ...
- [BZOJ4566][Haoi2016]找相同字符 后缀自动机+dp
4566: [Haoi2016]找相同字符 Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 1212 Solved: 694[Submit][Stat ...
- BZOJ 4566: [Haoi2016]找相同字符 [后缀自动机]
4566: [Haoi2016]找相同字符 Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 275 Solved: 155[Submit][Statu ...
- BZOJ 4566 JZYZOJ 1547 [haoi2016T5]找相同子串 后缀数组 并查集
http://172.20.6.3/Problem_Show.asp?id=1547 http://www.lydsy.com/JudgeOnline/problem.php?id=4566 单纯后缀 ...
- BZOJ4566: [Haoi2016]找相同字符(后缀自动机)
题意 题目链接 Sol 直接在SAM上乱搞 枚举前缀,用SAM统计可以匹配的后缀,具体在匹配的时候维护和当前节点能匹配的最大值 然后再把parent树上的点的贡献也统计上,这部分可以爆跳parent树 ...
- bzoj4566 找相同字符
题意:给定两个字符串,从中各取一个子串使之相同,有多少种取法.允许本质相同. 解:建立广义后缀自动机,对于每个串,分别统计cnt,之后每个点的cnt乘起来.记得开long long #include ...
- HAOI2016 找相同字符 后缀自动机
两个串,考虑一建一跑.枚举模式串的位置\(i\),考虑每次统计以\(i\)结尾的所有符合要求的串.在后缀自动机上走时记录当前匹配长度\(curlen\),则当前节点的贡献是\((curlen-len[ ...
- bzoj4566 / P3181 [HAOI2016]找相同字符
P3181 [HAOI2016]找相同字符 后缀自动机 (正解应是广义后缀自动机) 并不会广义后缀自动机. 然鹅可以用普通的后缀自动机. 我们先引入一个问题:算出从一个串内取任意两个不重合子串完全 ...
随机推荐
- docker dead but pid file exists
CentOS 6安装docker 报docker dead but pid file exists 执行 yum install epel-release yum install docker-io ...
- [Python Study Notes]正则表达式
正则表达式 正则表达式是一个特殊的字符序列,它能帮助你方便的检查一个字符串是否与某种模式匹配. Python 自1.5版本起增加了re 模块,它提供 Perl 风格的正则表达式模式. re 模块使 P ...
- Activity工作过程
Activity工作过程: Activity.startActivity--> Activity.startActivityForResult--> Instrumentation.exe ...
- day1(变量、常量、注释、用户输入、数据类型)
一.变量 name = "SmallNine" 等号前面是变量名(标识符),等号后面是变量值 变量的主要作用:就是把程序运算的中间结果临时存到内存里,已备后面的代码继续调用. 变量 ...
- Java Enum总结
枚举类型 枚举类型是Java5新增的特性之一,枚举是一种特殊类型的类,其枚举的每一个值 都是该枚举类的一个实例.枚举类型是作为Java语言的一部分,是完全类型安全的, 编译器会帮助我们检查枚举类型的正 ...
- 【视频编解码·学习笔记】8. 熵编码算法:基本算法列举 & 指数哥伦布编码
一.H.264中的熵编码基本方法: 熵编码具有消除数据之间统计冗余的功能,在编码端作为最后一道工序,将语法元素写入输出码流 熵解码作为解码过程的第一步,将码流解析出语法元素供后续步骤重建图像使用 在H ...
- ubuntu常用命令操作
建立文件夹软链接 ln -s 源文件 目标文件 当我们需要在不同的目录,用到相同的文件时,我们不需要在每一个需要的目录下都放一个必须相同的文件,我们只要在某个固定的目录,放上该文件,然后在其它的目录下 ...
- accordion 分类
<!--accordion--><h1>accordion 分类</h1><div id="accordionId" class=&quo ...
- Android热修复技术选型——三大流派解析
声明,本文转载自微信公众号文章 2015年以来,Android开发领域里对热修复技术的讨论和分享越来越多,同时也出现了一些不同的解决方案,如QQ空间补丁方案.阿里AndFix以及微信Tinker,它们 ...
- 八爪鱼采集器︱加载更多、再显示20条图文教程(Xpatth、Ajax)
每每以为攀得众山小,可.每每又切实来到起点,大牛们,缓缓脚步来俺笔记葩分享一下吧,please~ --------------------------- 由于代码布置采集器比较麻烦,又很早知道八爪鱼采 ...