二分答案,(具体可见http://blog.csdn.net/neither_nor/article/details/51669114),然后就是判定问题,sa和sam都可以做,用sam写了一下,先用sam建后缀树,然后用主席树维护right集合就好了,每次判断把对应节点倍增到深度为mid的点,然后看一下他的子树里有没有right在对应区间的点就好了。

(前几天用sa写了一下,bz能A,洛谷一直WA,有空重构吧。。。)

#include<iostream>
#include<cstring>
#include<cmath>
#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
const int maxn=,maxm=;
int a,b,c,d,t,pos[maxn],cnt=,cur,fa[maxn],ch[maxn][],dis[maxn],n,m,tot;
char s[maxn];
int add(int c,int p){
cur=++cnt;dis[cur]=dis[p]+;
for(;p&&!ch[p][c];p=fa[p])ch[p][c]=cur;
if(!p)fa[cur]=;
else{
int q=ch[p][c];
if(dis[q]==dis[p]+)fa[cur]=q;
else{
int nt=++cnt;dis[nt]=dis[p]+;
memcpy(ch[nt],ch[q],sizeof(ch[]));
fa[nt]=fa[q];fa[q]=fa[cur]=nt;
for(;p&&ch[p][c]==q;p=fa[p])ch[p][c]=nt;
}
}
return cur;
}
vector<int>tong[maxn];
int root[maxn],siz[maxn],tim,last[maxn*],pre[maxn*],other[maxn*],f[maxn][],dfn[maxn],from[maxn];
void insert(int x,int y){++t;pre[t]=last[x];last[x]=t;other[t]=y;}
void dfs(int x){
siz[x]=;dfn[x]=++tim;from[tim]=x;
for(int i=last[x];i;i=pre[i]){
int v=other[i];
f[v][]=x;dfs(v);
siz[x]+=siz[v];
}
}
int jump(int x,int y){
for(int i=;i>=;--i){
if(dis[f[x][i]]>=y)x=f[x][i];
}
return x;
}
struct node{
int l,r,v;
}tr[maxm];
void build(int pos,int l,int r,int &x){
++tot;tr[tot]=tr[x];x=tot;++tr[x].v;
if(l==r)return;
int mid=l+r>>;
if(pos<=mid)build(pos,l,mid,tr[x].l);
else build(pos,mid+,r,tr[x].r);
}
int qs(int i,int j,int l,int r,int L,int R){
if(r<L||l>R||r<l)return ;
if(l>=L&&r<=R)return tr[j].v-tr[i].v;
int mid=l+r>>;
return qs(tr[i].l,tr[j].l,l,mid,L,R)+qs(tr[i].r,tr[j].r,mid+,r,L,R);
}
int pd(int mid){
int op=jump(pos[c],mid);
return qs(root[dfn[op]-],root[dfn[op]+siz[op]-],,n,a,b-mid+);
}
int main(){
//freopen("data.in","r",stdin);
//freopen("data.out","w",stdout);
int tmp=;
cin>>n>>m;
scanf("%s",s+);
for(int i=n;i>=;--i){
tmp=add(s[i]-'a',tmp);
pos[i]=tmp;
tong[pos[i]].push_back(i);
}
for(int i=;i<=cnt;++i)insert(fa[i],i);dfs();
for(int j=;j<=;++j)
for(int i=;i<=cnt;++i){
f[i][j]=f[f[i][j-]][j-];
}
for(int i=;i<=tim;++i){
int siz=tong[from[i]].size();root[i]=root[i-];
for(int j=;j<siz;++j){
build(tong[from[i]][j],,n,root[i]);
}
}
for(int i=;i<=m;++i){
scanf("%d%d%d%d",&a,&b,&c,&d);
int l=,r=min(d-c+,b-a+),ans=;
while(l<=r){
int mid=l+r>>;
if(pd(mid))ans=mid,l=mid+;
else r=mid-;
}
printf("%d\n",ans);
}
//fclose(stdin);
//fclose(stdout);
//system("pause");
return ;
}
/*
50 1
pnzogoobycwczqfrbylxuwkgmnzlekbcakviijcrjahthagkcn
20 47 8 50
*/

bzoj4556(sam)的更多相关文章

  1. 字符串(tjoi2016,heoi2016,bzoj4556)(sam(后缀自动机)+线段树合并+倍增+二分答案)

    佳媛姐姐过生日的时候,她的小伙伴从某东上买了一个生日礼物.生日礼物放在一个神奇的箱子中.箱子外边写了 一个长为\(n\)的字符串\(s\),和\(m\)个问题.佳媛姐姐必须正确回答这\(m\)个问题, ...

  2. 2019.02.27 bzoj4556: [Tjoi2016&Heoi2016]字符串(二分答案+sam+线段树合并)

    传送门 题意:给一个字符串SSS. 有mmm次询问,每次给四个参数a,b,c,da,b,c,da,b,c,d,问s[a...b]s[a...b]s[a...b]的所有子串和s[x...y]s[x... ...

  3. SAM初探

    SAM,即Suffix Automaton,后缀自动机. 关于字符串有很多玩法,有很多算法都是围绕字符串展开的.为什么?我的理解是:相较于数字组成的序列,字母组成的序列中每个单位上元素的个数是有限的. ...

  4. bzoj4199:NOI2015D2T2品酒大会(SAM版)

    SAM感觉写起来比SA更直观(?) #include <iostream> #include <cstdio> #include <cstring> #includ ...

  5. SAM/BAM文件处理

    当测序得到的fastq文件map到基因组之后,我们通常会得到一个sam或者bam为扩展名的文件.SAM的全称是sequence alignment/map format.而BAM就是SAM的二进制文件 ...

  6. hihocoder SAM基础概念

    后缀自动机一·基本概念 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi:今天我们来学习一个强大的字符串处理工具:后缀自动机(Suffix Automaton,简称 ...

  7. BZOJ4556: [Tjoi2016&Heoi2016]字符串

    Description 佳媛姐姐过生日的时候,她的小伙伴从某东上买了一个生日礼物.生日礼物放在一个神奇的箱子中.箱子外边写了 一个长为n的字符串s,和m个问题.佳媛姐姐必须正确回答这m个问题,才能打开 ...

  8. bam/sam格式说明

    在SAM输出的结果中每一行都包括十二项通过Tab分隔,从左到右分别是: 1 序列的名字(Read的名字) 2 概括出一个合适的标记,各个数字分别代表 1     序列是一对序列中的一个 2     比 ...

  9. mismatch位置(MD tag)- sam/bam格式解读进阶

    这算是第二讲了,前面一讲是:Edit Distance编辑距离(NM tag)- sam/bam格式解读进阶 MD是mismatch位置的字符串的表示形式,貌似在call SNP和indel的时候会用 ...

随机推荐

  1. linux 获取帮助的命令

    Linux命令详解:[7]获得命令帮助 听语音 | 浏览:4601 | 更新:2015-01-30 20:21 | 标签:linux 1 2 3 4 5 分步阅读 在维护和使用Linux系统时,常常会 ...

  2. mybatis xml中返回map 参看aiwanpai

    <!-- 指定日期活动被创建次数查询结果数据集--> <resultMap id="countPlayTimesMap" type="HashMap&q ...

  3. redis-缓存失效三种策略(FIFO 、LRU、LFU)

    缓存失效策略(FIFO .LRU.LFU三种算法的区别) 当缓存需要被清理时(比如空间占用已经接近临界值了),需要使用某种淘汰算法来决定清理掉哪些数据.常用的淘汰算法有下面几种: FIFO:First ...

  4. js对象拷贝遇到的坑

    问题:通过拷贝赋值后,所有的对象的name居然都是C test(){ let person = [{'name':'danny'}] let names = ['A','B','C'] let tem ...

  5. 学习日 day1

    今天第一天开始写博客,希望以后能坚持,每天写,一是记录自己学习的历程,更重要的是复习每天学过的东西. 今天学习的内容:time模块的相关语法 导入方式 首行输入import time即可 time.t ...

  6. java引用

    java1.2之后将引用分为强引用(Strong Reference).软引用(Soft Reference).弱引用(Weak Reference).虚引用(Phantom Reference)4种 ...

  7. idea2017启动ssm项目卡在build阶段后报outofmemory

    如上图,设置build process heap size(Mbytes)(构建过程堆大小(单位MB))为4000,即约4GB.之前设置的是700,修改之后问题解决. 补充:导入新项目后,此参数会初始 ...

  8. input text 只能输入数字

    添加 onkeyup="value=value.replace(/[^\d]/g,'')"

  9. [leetcode]34.Find First and Last Position of Element in Sorted Array找区间

    Given an array of integers nums sorted in ascending order, find the starting and ending position of ...

  10. Linux磁盘空间分析及清理(df、du、rm)

    1.df磁盘空间查看 df可以查看一级文件夹大小.使用比例.档案系统及其挂入点. [root@oms ~]# df -Th Filesystem Type Size Used Avail Use% M ...