LOJ6041 SAM+set+树状数组
首先对于原串建\(SAM\),我们可以发先在一个点\(i\)的\(right\)集合里的点的相似度就是\(len[i]\),于是可以将\(SAM\)的\(right\)集合通过\(set\)来启发式合并,每次加入新的点对\((i,j,len[i])\),最后离线询问二维数点就可以解决了
但是这样每次维护\(set\)加入的点对是平方级别的的 我们可以发现对于一个要加入的点\(i\)只需要找\(set\)里和他相邻的两个点 将他们的点对加入就好 其余点对不会影响答案
复杂度\(O(nlog^2n)\)
具体的看代码吧
#include<bits/stdc++.h>
using namespace std;
#define FO(x) {freopen(#x".in","r",stdin);freopen(#x".out","w",stdout);}
#define pa pair<int,int>
#define mod 1000000007
#define ll long long
#define mk make_pair
#define pb push_back
#define fi first
#define se second
#define cl(x) memset(x,0,sizeof x)
#ifdef Devil_Gary
#define bug(x) cout<<(#x)<<" "<<(x)<<endl
#define debug(...) fprintf(stderr, __VA_ARGS__)
#else
#define bug(x)
#define debug(...)
#endif
#define lowbit(x) x&(-x)
const int INF = 0x7fffffff;
const int N=2e5+5;
/*
char *TT,*mo,but[(1<<15)+2];
#define getchar() ((TT==mo&&(mo=(TT=but)+fread(but,1,1<<15,stdin),TT==mo))?-1:*TT++)//*/
inline int read(){
int x=0,rev=0,ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')rev=1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return rev?-x:x;
}
set<int>st[N];
typedef set<int>::iterator iter;
struct data{
int x,y,val;
}t[N],a[N<<5];
int lst,rt,n,m,sz,tot,ans[N],len[N],c[N][2],par[N],w[N],b[N],s[N];
char ss[N];
void extend(int x){
int np=++sz,p=lst;
len[np]=len[p]+1,lst=np;
for(;p&&!c[p][x];p=par[p]) c[p][x]=np;
if(!p) par[np]=rt;
else{
int q=c[p][x];
if(len[q]==len[p]+1) par[np]=q;
else{
int nq=++sz;
memcpy(c[nq],c[q],sizeof c[q]);
len[nq]=len[p]+1,par[nq]=par[q];
par[q]=par[np]=nq;
for(;p&&c[p][x]==q;p=par[p]) c[p][x]=nq;
}
}
}
void pre(){
for(int i=1;i<=sz;i++) w[len[i]]++;
for(int i=1;i<=sz;i++) w[i]+=w[i-1];
for(int i=sz;i;i--) b[w[len[i]]--]=i;
for(int i=sz;i>=2;i--){
int x=b[i],y=par[x];
if(st[x].size()>st[y].size()) swap(st[x],st[y]);
for(iter it=st[x].begin();it!=st[x].end();++it){
// iter w=lower_bound(st[y].begin(),st[y].end(),*it);
iter w=st[y].lower_bound(*it);
if(w!=st[y].end()) a[++tot]=(data){*it,*w,len[y]};
if(w!=st[y].begin()) a[++tot]=(data){*(--w),*it,len[y]};
}
for(iter it=st[x].begin();it!=st[x].end();it++) st[y].insert(*it);
}
}
bool cmp(data a,data b){
return a.x>b.x;
}
void add(int x,int v){
for(int i=x;i<=n;i+=lowbit(i)) s[i]=max(s[i],v);
}
int Query(int x){
int ans=0;
for(int i=x;i;i-=lowbit(i)) ans=max(ans,s[i]);
return ans;
}
int main(){
#ifdef Devil_Gary
freopen("A7.in","r",stdin);
#endif
n=read(),m=read(),rt=lst=sz=1,scanf("%s",ss+1);
for(int i=1;i<=n;i++) extend(ss[i]-'0'),st[lst].insert(i);
for(int i=1;i<=m;i++) t[i].x=read(),t[i].y=read(),t[i].val=i;
pre(),sort(t+1,t+m+1,cmp),sort(a+1,a+tot+1,cmp);
for(int i=1,j=1;i<=m;i++){
for(;j<=tot&&a[j].x>=t[i].x;j++) add(a[j].y,a[j].val);
ans[t[i].val]=Query(t[i].y);
}
for(int i=1;i<=m;i++) printf("%d\n",ans[i]);
}
LOJ6041 SAM+set+树状数组的更多相关文章
- P7046-「MCOI-03」诗韵【SAM,倍增,树状数组】
正题 题目链接:https://www.luogu.com.cn/problem/P7046 题目大意 给出一个长度为 \(n\) 的字符串,然后 \(m\) 次把它的一个子串加入集合.如果一个字符串 ...
- 【loj6041】「雅礼集训 2017 Day7」事情的相似度 后缀自动机+STL-set+启发式合并+离线+扫描线+树状数组
题目描述 给你一个长度为 $n$ 的01串,$m$ 次询问,每次询问给出 $l$ .$r$ ,求从 $[l,r]$ 中选出两个不同的前缀的最长公共后缀长度的最大值. $n,m\le 10^5$ 题解 ...
- BZOJ 2754 [SCOI2012]喵星球上的点名 (AC自动机、树状数组)
吐槽: 为啥很多人用AC自动机暴力跳都过了?复杂度真的对么? 做法一: AC自动机+树状数组 姓名的问题,中间加个特殊字符连起来即可. 肯定是对点名串建AC自动机(map存儿子),然后第一问就相当于问 ...
- BZOJ 2780 Sevenk Love Oimaster (后缀自动机+树状数组+dfs序+离线)
题目大意: 给你$n$个大串和$m$个询问,每次给出一个字符串$s$询问在多少个大串中出现过 好神的一道题 对$n$个大串建出广义$SAM$,建出$parent$树 把字符串$s$放到$SAM$里跑, ...
- 51nod 麦克打电话(AC自动机+树状数组)
SAM+线段树合并的裸题. 但我们讨论AC自动机的做法. 先建出AC自动机.考虑询问在[a,b]中出现的次数就是\([1,b]\)的出现次数-\([1,a-1]\)的出现次数.把询问离线.然后我们要求 ...
- BZOJ 1103: [POI2007]大都市meg [DFS序 树状数组]
1103: [POI2007]大都市meg Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2221 Solved: 1179[Submit][Sta ...
- bzoj1878--离线+树状数组
这题在线做很麻烦,所以我们选择离线. 首先预处理出数组next[i]表示i这个位置的颜色下一次出现的位置. 然后对与每种颜色第一次出现的位置x,将a[x]++. 将每个询问按左端点排序,再从左往右扫, ...
- codeforces 597C C. Subsequences(dp+树状数组)
题目链接: C. Subsequences time limit per test 1 second memory limit per test 256 megabytes input standar ...
- BZOJ 2434: [Noi2011]阿狸的打字机 [AC自动机 Fail树 树状数组 DFS序]
2434: [Noi2011]阿狸的打字机 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 2545 Solved: 1419[Submit][Sta ...
随机推荐
- ES系列二、CentOS7安装ES head6.3.1
1.Head插件简介 ElasticSearch-head是一个H5编写的ElasticSearch集群操作和管理工具,可以对集群进行傻瓜式操作. 显示集群的拓扑,并且能够执行索引和节点级别操作 搜索 ...
- H3C SNMP OID
有两种mib-style [1]老些的设备 cpu 使用率OID: .1.3.6.1.4.1.25506.2.6.1.1.1.1.6.slot 内存使用率OID: .1.3.6.1.4.1.2550 ...
- svn的常用命令
svn :看log.版本库.增删.提交 (1)svn up //代码更新到最新版本. (2)svn checkout //将代码checkout出来. (3)svn revert -R ./ //将代 ...
- 红黑树与AVL树
概述:本文从排序二叉树作为引子,讲解了红黑树,最后把红黑树和AVL树做了一个比较全面的对比. 1 排序二叉树 排序二叉树是一种特殊结构的二叉树,可以非常方便地对树中所有节点进行排序和检索. 排序二叉树 ...
- 028_rync和inotify实现实时备份
一.服务节点安装inotify-tools. 确保系统后以下输出=> [root@xxxx]# ll /proc/sys/fs/inotify/ total 0 -rw-r--r-- 1 roo ...
- 利用mysqltuner工具对mysql数据库进行优化
mysqltuner工具使用,本工具建议定期运行,发现目前MYSQL数据库存在的问题及修改相关的参数 工具的下载及部署 解决环境依赖,因为工具是perl脚本开发的,需要perl脚本环境 # yun i ...
- python风流史
python的创始人为吉多·范罗苏姆(Guido van Rossum).1989年的圣诞节期间,吉多·范罗苏姆(中文名字:龟叔)为了在阿姆斯特丹打发时间,决心开发一个新的脚本解释程序,作为ABC语言 ...
- Appium+Java(一) Windows环境搭建篇
准备: Android版本 :4.2.2 nodejs版本:5.6.0 appium版本:v1.4.16 1. 安卓SDK及配置环境变量 1.1.先下载sdk安装包:installer_r24.4.1 ...
- FineReport——获取控件值和单元格值
设置单元格的值(填报预览): //contentPane.setCellValue(1,0,"abc");//参数面板给单元格赋实际值,即可填报 contentPane.curLG ...
- poj1179 环形+区间dp
因为要用到模,所以左起点设置为0比较好 #include<iostream> #include<cstdio> #include<cstring> #define ...