bzoj 4556 [Tjoi2016&Heoi2016]字符串
来源:互联网 发布:37龙神契约进阶数据库 编辑:程序博客网 时间:2024/06/16 19:23
4556: [Tjoi2016&Heoi2016]字符串
Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 986 Solved: 386
[Submit][Status][Discuss]
Description
佳媛姐姐过生日的时候,她的小伙伴从某东上买了一个生日礼物。生日礼物放在一个神奇的箱子中。箱子外边写了
一个长为n的字符串s,和m个问题。佳媛姐姐必须正确回答这m个问题,才能打开箱子拿到礼物,升职加薪,出任CE
O,嫁给高富帅,走上人生巅峰。每个问题均有a,b,c,d四个参数,问你子串s[a..b]的所有子串和s[c..d]的最长公
共前缀的长度的最大值是多少?佳媛姐姐并不擅长做这样的问题,所以她向你求助,你该如何帮助她呢?
Input
输入的第一行有两个正整数n,m,分别表示字符串的长度和询问的个数。接下来一行是一个长为n的字符串。接下来
m行,每行有4个数a,b,c,d,表示询问s[a..b]的所有子串和s[c..d]的最长公共前缀的最大值。1<=n,m<=100,000,
字符串中仅有小写英文字母,a<=b,c<=d,1<=a,b,c,d<=n
Output
对于每一次询问,输出答案。
Sample Input
5 5
aaaaa
1 1 1 5
1 5 1 1
2 3 2 3
2 4 2 3
2 3 2 4
aaaaa
1 1 1 5
1 5 1 1
2 3 2 3
2 4 2 3
2 3 2 4
Sample Output
1
1
2
2
2
1
2
2
2
HINT
Source
【分析】
可持久化线段树+后缀数组+二分答案
YY一下发现,[a,b]区间中与rank[c]最近的rank[x],也就是rank数组中rank[c]在数值上的前驱后继,答案最优。
二分一发答案,可持久化线段树找一下前驱后继这题就做完了。
WA了好几次,结果是因为后缀数组求错了。
唉,求尼玛老公抱
【代码】
//bzoj 4556 字符串#include<bits/stdc++.h>#define ll long long#define M(a) memset(a,0,sizeof a)#define fo(i,j,k) for(i=j;i<=k;i++)using namespace std;const int mxn=400005;const int M=4000005;char s[mxn];int n,m,T,tot,A,B,C,D,Q,len;int ls[M],rs[M],c[M],root[mxn];int a[mxn],b[mxn],x[mxn],y[mxn];int sa[mxn],rank[mxn],height[mxn],st[mxn][30];inline void build(int l,int r,int u,int &v,int w){ v=(++tot),c[v]=c[u]+1; if(l==r) return; int mid=l+r>>1; ls[v]=ls[u],rs[v]=rs[u]; if(w<=mid) build(l,mid,ls[u],ls[v],w); else build(mid+1,r,rs[u],rs[v],w);}inline int pre(int l,int r,int u,int v,int w){ int mid=l+r>>1; if(c[v]==c[u]) return 0; if(l==r) return l; if(w<=mid) return pre(l,mid,ls[u],ls[v],w); else { int tmp=pre(mid+1,r,rs[u],rs[v],w); if(tmp) return tmp; return pre(l,mid,ls[u],ls[v],w); }}inline int nxt(int l,int r,int u,int v,int w){ int mid=l+r>>1; if(c[v]==c[u]) return 0; if(l==r) return l; int Le=c[ls[v]]-c[ls[u]],Re=c[rs[v]]-c[rs[u]]; if(w>mid) return nxt(mid+1,r,rs[u],rs[v],w); else { int tmp=nxt(l,mid,ls[u],ls[v],w); if(tmp) return tmp; return nxt(mid+1,r,rs[u],rs[v],w); }}inline bool comp(int i,int j,int l){ return y[i]==y[j] && (i+l>len?-1:y[i+l])==(j+l>len?-1:y[j+l]);}inline void work(){ int i,j,k,p;m=30; scanf("%d%d",&len,&Q); scanf("%s",s+1); fo(i,1,len) a[i]=s[i]-'a'+1; fo(i,0,m) b[i]=0; fo(i,1,len) b[x[i]=a[i]]++; fo(i,1,m) b[i]+=b[i-1]; for(i=len;i>=1;i--) sa[b[x[i]]--]=i; for(k=1;k<=len;k<<=1) { p=0; fo(i,len-k+1,len) y[++p]=i; fo(i,1,len) if(sa[i]>k) y[++p]=sa[i]-k; fo(i,0,m) b[i]=0; fo(i,1,len) b[x[y[i]]]++; fo(i,1,m) b[i]+=b[i-1]; for(i=len;i>=1;i--) sa[b[x[y[i]]]--]=y[i]; swap(x,y),p=2,x[sa[1]]=1; fo(i,2,len) x[sa[i]]=comp(sa[i-1],sa[i],k)?p-1:p++; if(p>len) break; m=p; } p=k=0; fo(i,1,len) rank[sa[i]]=i; for(i=1;i<=len;height[rank[i++]]=k) for(k?k--:0,j=sa[rank[i]-1];a[i+k]==a[j+k];k++); fo(i,1,len) st[i][0]=height[i]; fo(j,1,18) fo(i,1,len) if(i+(1<<j-1)<=len) st[i][j]=min(st[i][j-1],st[i+(1<<j-1)][j-1]);}inline int mn(int x,int y){ if(x==rank[y]) return len-y+1; y=rank[y]; if(x>y) swap(x,y); x++;int k=0; while(x+(1<<k+1)<=y) k++; return min(st[x][k],st[y-(1<<k)+1][k]);}inline bool check(int mid){ int i,l=A,r=B-mid+1; int p=pre(1,len,root[l-1],root[r],rank[C]); int q=nxt(1,len,root[l-1],root[r],rank[C]); if(p>=1 && p<=len && mn(p,C)>=mid) return 1; if(q>=1 && q<=len && mn(q,C)>=mid) return 1; return 0;}int main(){//freopen("rand.txt","r",stdin);//freopen("WA.txt","w",stdout); int i,j; work(); fo(i,1,len) build(1,len,root[i-1],root[i],rank[i]); //fo(i,1,len) printf("root[%d]=%d\n",i,root[i]); while(Q--) { scanf("%d%d%d%d",&A,&B,&C,&D); int l=0,r=min(B-A+1,D-C+1); while(l<r) { int mid=l+r+1>>1; if(check(mid)) l=mid; else r=mid-1; } printf("%d\n",l); } return 0;}
阅读全文
0 0
- BZOJ 4556 [Tjoi2016&Heoi2016]字符串
- bzoj 4556 [Tjoi2016&Heoi2016]字符串
- bzoj 4556 [Tjoi2016&Heoi2016]字符串
- bzoj 4556 [Tjoi2016&Heoi2016]字符串
- 4556: [Tjoi2016&Heoi2016]字符串
- 4556: [Tjoi2016&Heoi2016]字符串
- 4556: [Tjoi2016&Heoi2016]字符串
- [后缀数组 主席树] BZOJ 4556 [Tjoi2016&Heoi2016]字符串
- BZOJ 4556: [Tjoi2016&Heoi2016]字符串 后缀数组 主席树
- [达成成就:Tjoi2016&Heoi2016全AC] bzoj 4556: [Tjoi2016&Heoi2016]字符串 后缀数组+可持久化线段树
- 4556: [Tjoi2016&Heoi2016]字符串 后缀自动机 详细
- BZOJ4556: [Tjoi2016&Heoi2016]字符串
- Bzoj4556: [Tjoi2016&Heoi2016]字符串
- BZOJ4556 [Tjoi2016&Heoi2016]字符串
- bzoj4556【TJOI2016&HEOI2016】字符串
- BZOJ4556: [Tjoi2016&Heoi2016]字符串
- [Tjoi2016&Heoi2016]字符串
- JZOJ4614. 【TJOI2016&HEOI2016】字符串
- CGContext 小记
- 解析构造函数与析构函数中 调用虚函数的原理
- PHP curl模拟ip和来源进行访问
- 计算机语言概述(笔记)
- CFAbsoluteTimeGetCurrent
- bzoj 4556 [Tjoi2016&Heoi2016]字符串
- Ubuntu中vi命令使用
- CGAffineTransformMake(a,b,c,d,tx,ty) 矩阵运算的原理
- 精通Dubbo——dubbo2.0源码中Spring Bean的加载
- UIImage的imageOrientation属性(app中图片旋转了的bug)
- CodeVS 2924 数独挑战 题解
- 股票折线图demo(兼容SDK7编译,ios7)
- iOS5&iOS6 Grouped类型UITableView背景色设置问题
- easyui-combotree实现树形结构的下拉控件,并实现节点回显