BZOJ 4566 JZYZOJ 1547 [haoi2016T5]找相同子串 后缀数组 并查集
http://172.20.6.3/Problem_Show.asp?id=1547
http://www.lydsy.com/JudgeOnline/problem.php?id=4566
单纯后缀数组是O(n^2)应该是40分
似乎后缀自动机是正解。
但是后缀数组+并查集也可以乱搞a掉,这里写的是并查集写法,也算是get了一个并查集的用法,某种意义上并查集可以用来维护区间最大值最小值的贡献,实现方法见代码。
定义字符串大小的整型变量时候,
char siz;
导致re什么的,
我大概是个zz。
顺便存个板子,抄紫萱学姐的板子。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int maxn=;
const int pl=;
int sa[maxn*+pl]={};//排名第i的是从sa[i]开始的数组
int rk[maxn*+pl]={};//i的排名
int height[maxn*+pl]={};//排名第i的与排名第i-1的最长相同前缀长度
int temp[maxn*+pl]={};//暂时的排名
int cnt[maxn*+pl]={};//第i种(字典序)前缀的有多少个(的前缀和)
int p[maxn*+pl]={};//临时对这一次需要用的sa的储存,处理了后缀长度不同的情况。
char ch[maxn*+pl]={},ch1[maxn]={},ch2[maxn]={};
int siz1,siz2,siz;
int fa[maxn*+pl]={},a[maxn*+pl]={},lef[maxn*+pl]={},rig[maxn*+pl]={};
inline bool equ(int x,int y,int l){return rk[x]==rk[y]&&rk[x+l]==rk[y+l];}
void SA(){
for(int i=;i<=siz;i++)rk[i]=ch[i],sa[i]=i;
for(int i,sig=,l=,pos=;pos<siz;sig=pos){//l从0开始是预处理
pos=;
for(i=siz-l+;i<=siz;i++)p[++pos]=i;
for(i=;i<=siz;i++)if(sa[i]>l)p[++pos]=sa[i]-l;
for(i=;i<=sig;i++)cnt[i]=;
for(i=;i<=siz;i++)cnt[rk[p[i]]]++;
for(i=;i<=sig;i++)cnt[i]+=cnt[i-];
for(i=siz;i>;i--){sa[cnt[rk[p[i]]]]=p[i];cnt[rk[p[i]]]--;}
pos=;
for(i=;i<=siz;i++){
if(equ(sa[i],sa[i-],l))temp[sa[i]]=pos ;
else temp[sa[i]]=++pos;
}for(i=;i<=siz;i++)rk[i]=temp[i];
if(l==)l=;
else l<<=;
}
for(int i=,k=;i<=siz;i++){
/*对于每一个位置的后缀,下一个位置的后缀可匹配的最短长度
一定大于等于该位置可匹配的长度-1,显然。所以是O(n)的算法
*/
if(rk[i]==){k=;continue;}
if(k>)k--;
int j=sa[rk[i]-];
while(ch[i+k]==ch[j+k])k++;
height[rk[i]]=k;
}
}
bool mcmp(int x,int y){return height[x]>height[y];}
int getfa(int x){
if(x!=fa[x])fa[x]=getfa(fa[x]);
return fa[x];
}
int main(){
//freopen("a.in","r",stdin);
scanf("%s",&ch1);siz1=strlen(ch1);
scanf("%s",&ch2);siz2=strlen(ch2);
ch[siz1+]='z'+;siz=siz1+siz2+;
for(int i=;i<siz1;i++)ch[i+]=ch1[i];
for(int i=;i<siz2;i++)ch[siz1++i]=ch2[i];
SA();
for(int i=;i<=siz;i++){
a[i]=fa[i]=i;
lef[i]=(sa[i]<=siz1);
rig[i]=^lef[i];
}sort(a+,a++siz,mcmp);
long long ans=;
int x,y;
for(int i=;i<=siz;i++){
if(a[i]==)continue;
x=getfa(a[i]);y=getfa(a[i]-);
ans+=(long long)height[a[i]]*(long long)(lef[x]*rig[y]+rig[x]*lef[y]);
lef[x]+=lef[y];rig[x]+=rig[y];fa[y]=x;
}printf("%lld\n",ans);
return ;
}
更新:http://www.cnblogs.com/137shoebills/p/8511439.html 这是一道板子题的代码,注释应该被我完善了,更加清晰一点,所以我为什么要先写一道组合题再写板子啊喂。
BZOJ 4566 JZYZOJ 1547 [haoi2016T5]找相同子串 后缀数组 并查集的更多相关文章
- BZOJ 4199: [Noi2015]品酒大会( 后缀数组 + 并查集 )
求出后缀数组后, 对height排序, 从大到小来处理(r相似必定是0~r-1相似), 并查集维护. 复杂度O(NlogN + Nalpha(N)) ------------------------- ...
- BZOJ 4199 [Noi2015]品酒大会:后缀数组 + 并查集
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=4199 题意: 给你一个长度为n的字符串s,和一个长为n的数组v. 对于每个整数r∈[0,n ...
- URAL 1297 最长回文子串(后缀数组)
1297. Palindrome Time limit: 1.0 secondMemory limit: 64 MB The “U.S. Robots” HQ has just received a ...
- poj 2774 最长公共子串 后缀数组
Long Long Message Time Limit: 4000MS Memory Limit: 131072K Total Submissions: 25752 Accepted: 10 ...
- poj 1743 Musical Theme(最长重复子串 后缀数组)
poj 1743 Musical Theme(最长重复子串 后缀数组) 有N(1 <= N <=20000)个音符的序列来表示一首乐曲,每个音符都是1..88范围内的整数,现在要找一个重复 ...
- BZOJ 3230 相似子串 | 后缀数组 二分 ST表
BZOJ 3230 相似子串 题面 题解 首先我们要知道询问的两个子串的位置. 先正常跑一遍后缀数组并求出height数组. 对于每一个后缀suffix(i),考虑以i开头的子串有多少是之前没有出现过 ...
- bzoj 3230 相似子串——后缀数组
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3230 作出后缀数组,从 LCP 看每个位置对于本质不同子串的贡献,而且他们已经按前面部分排好 ...
- BZOJ 1396: 识别子串( 后缀数组 + 线段树 )
这道题各位大神好像都是用后缀自动机做的?.....蒟蒻就秀秀智商写一写后缀数组解法..... 求出Height数组后, 我们枚举每一位当做子串的开头. 如上图(x, y是height值), Heigh ...
- BZOJ 3230: 相似子串(后缀数组)
传送门 解题思路 其实题目挺好想的.首先子串排名可以由后缀数组求得,因为不算重复的,所以后缀数组的每个后缀排名的去掉\(lcp\)的前缀排名为当前后缀的子串排名.这样就可以预处理出每个后缀的\(l,r ...
随机推荐
- 【BZOJ】2693: jzptab 莫比乌斯反演
[题意]2154: Crash的数字表格 莫比乌斯反演,多组询问,T<=10000. [算法]数论(莫比乌斯反演) [题解]由上一题, $ans=\sum_{g\leq min(n,m)}g\s ...
- C语言实现栈(顺序存储方式)
#include <stdio.h> #include <stdlib.h> //提供malloc()原型 #include <stdbool.h> //提供tru ...
- hihoCoder #1175 : 拓扑排序·二
题目链接:http://hihocoder.com/problemset/problem/1175 代码实现如下: #include <queue> #include <cstdio ...
- NYOJ 1022 合纵连横 (并查集)
题目链接 描述 乱世天下,诸侯割据.每个诸侯王都有一片自己的领土.但是不是所有的诸侯王都是安分守己的,实力强大的诸侯国会设法吞并那些实力弱的,让自己的领土面积不断扩大.而实力弱的诸侯王为了不让自己的领 ...
- python3爬虫.1.简单的网页爬虫
此为记录下我自己的爬虫学习过程. 利用url包抓取网页 import urllib.request #url包 def main(): url = "http://www.douban.co ...
- 深入理解Spring系列之十:DispatcherServlet请求分发源码分析
转载 https://mp.weixin.qq.com/s/-kEjAeQFBYIGb0zRpST4UQ DispatcherServlet是SpringMVC的核心分发器,它实现了请求分发,是处理请 ...
- linux内存分配方法总结【转】
转自:http://www.bkjia.com/Linuxjc/443717.html 内存映射结构: 1.32位地址线寻址4G的内存空间,其中0-3G为用户程序所独有,3G-4G为内核占有. 2.s ...
- UVA题解二
UVA题解二 UVA 110 题目描述:输出一个Pascal程序,该程序能读入不多于\(8\)个数,并输出从小到大排好序后的数.注意:该程序只能用读入语句,输出语句,if语句. solution 模仿 ...
- php cache类代码(php数据缓存类)
如果访问量大的话会给数据库造成很大的负担,所以对于变化不经常的内容要做好php 数据cache(缓存)是十分必要的,我做了一个简单的php“文件缓存”的类,希望对大家有所帮助. 思路是这样的: 对于一 ...
- Eloquent中一些其他的create方法
firstOrCreate/ firstOrNew# 还有两种其它方法,你可以用来通过属性批量赋值创建你的模型:firstOrCreate 和firstOrNew.firstOrCreate 方法将会 ...