题链:

http://www.lydsy.com/JudgeOnline/problem.php?id=4556

题解:

巨恶心。。。但是题很好呀,可以练习好几个比较麻烦的算法~

1).预处理
首先用倍增算法求出 sa[],以及rank[],height[]。
并且对 height[]数组建立ST表。
按顺序对rank[]建立主席树。
(第i颗树的节点 u[l,r]保存了在 rank[1]~rank[i]这个前缀内,出现了多少个权值在 l~r内的rank值(num))

2).在线查询
对于一组询问(a,b,c,d),先二分答案 X,下面即是判定:
用rank[]数组得到后缀 c在后缀数组中的位置 P。
然后再求出在后缀数组中从p向上延伸到的最远位置 L,使得 LCP(L,P)>=X。
同理,向下延伸到最远位置 R,使得 LCP(P,R)>=X。
(求法呢,可以用二分,也可以用倍增求,类似倍增法求LCA,在求得时候需要用到 RMQ)
接下来,就要用到主席树了。
既然求出了与后缀c的LCP>=X的后缀在后缀数组中的排名范围[L,R]
那么就查询主席树 rt[a-1]~rt[b-X+1]中的权值区间 [L,R]的值num是否大于 0即可。
(如果 num>0,即表明在 S[a~b]内存在一个子串与后缀 c的LCP至少为 X)

复杂度:O(n*log2N*log2N),有点卡时间,BZOJ上花了 14S.

代码:

#include<cstdio>
#include<cstring>
#include<iostream>
#define MAXN 100005
#define rint register int
#define filein(x) freopen(#x".in","r",stdin);
#define fileout(x) freopen(#x".out","w",stdout);
using namespace std;
char S[MAXN];
int sa[MAXN],rak[MAXN],hei[MAXN],stm[MAXN][20],log2[MAXN];
struct CMT{//Chairman Tree (QAQ)int rt[MAXN],ls[MAXN*20],rs[MAXN*20],num[MAXN*20],siz;void pushup(int u){num[u]=num[ls[u]]+num[rs[u]];}void reset(int &u,int l,int r){u=++siz; num[u]=0;if(l==r) return;int mid=(l+r)>>1;reset(ls[u],l,mid);reset(rs[u],mid+1,r);}void build(int &u,int l,int r,int p,int v){u=++siz;if(l==r){num[u]=1; return;}ls[u]=ls[v]; rs[u]=rs[v];int mid=(l+r)>>1;if(p<=mid) build(ls[u],l,mid,p,ls[v]);else build(rs[u],mid+1,r,p,rs[v]);pushup(u);}int query(int lu,int ru,int l,int r,int al,int ar){//左开右闭if(al<=l&&r<=ar) return num[ru]-num[lu];int mid=(l+r)>>1,now=0;if(al<=mid) now+=query(ls[lu],ls[ru],l,mid,al,ar);if(mid<ar)now+=query(rs[lu],rs[ru],mid+1,r,al,ar);return now;}
}T;
void build(int N,int M){static int ta[MAXN],tb[MAXN],c[MAXN],*x,*y; x=ta; y=tb;for(rint i=0;i<M;i++) c[i]=0;for(rint i=0;i<N;i++) c[x[i]=S[i]]++;for(rint i=1;i<M;i++) c[i]+=c[i-1];for(rint i=N-1;i>=0;i--) sa[--c[x[i]]]=i;   for(rint k=1;k<N;k<<=1){int p=0;for(rint i=N-k;i<N;i++) y[p++]=i;for(rint i=0;i<N;i++) if(sa[i]>=k) y[p++]=sa[i]-k;for(rint i=0;i<M;i++) c[i]=0;for(rint i=0;i<N;i++) c[x[y[i]]]++;for(rint i=1;i<M;i++) c[i]+=c[i-1];for(rint i=N-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i];swap(x,y); y[N]=-1; M=1; x[sa[0]]=0;for(rint i=1;i<N;i++)x[sa[i]]=y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k]?M-1:M++;if(M>=N) break;}for(rint i=0;i<N;i++) rak[sa[i]+1]=i+1;for(rint i=0,h=0,j;i<N;i++){if(h) h--;if(rak[i+1]>1){j=sa[(rak[i+1]-1)-1];while(S[i+h]==S[j+h]) h++;}stm[rak[i+1]][0]=hei[rak[i+1]]=h;}for(rint k=1;k<=log2[N];k++)for(rint i=(1<<k);i<=N;i++)stm[i][k]=min(stm[i-(1<<(k-1))][k-1],stm[i][k-1]);
}
int LCP(int l,int r){if(l>r) swap(l,r); l++;int k=log2[r-l+1];return min(stm[l+(1<<k)-1][k],stm[r][k]);
}
int multiply_find(int p,int x,int y,int N){int q=p;for(rint k=log2[N],Q;k>=0;k--){Q=q+(1<<k)*y;if(Q<1||Q>N) continue;if(LCP(Q,p)<x) continue;q=Q;}return q;
}
bool check(int x,int a,int b,int c,int d,int N){int L=multiply_find(rak[c],x,-1,N);int R=multiply_find(rak[c],x,1,N);int Lu=a-1,Ru=b-x+1;return T.query(T.rt[Lu],T.rt[Ru],1,N,L,R);
}
int binary_ans(int l,int r,int a,int b,int c,int d,int N){int mid,ans=0;while(l<=r){mid=(l+r)>>1;if(check(mid,a,b,c,d,N)) ans=mid,l=mid+1;else r=mid-1;}return ans;
}
int main()
{//filein(str); fileout(str);log2[1]=0;for(rint i=2;i<=100000;i++) log2[i]=log2[i>>1]+1;int N,M,a,b,c,d;scanf("%d%d",&N,&M);scanf("%s",S); build(N,300);T.reset(T.rt[0],1,N);for(rint i=0;i<N;i++)T.build(T.rt[i+1],1,N,rak[i+1],T.rt[i]);for(rint i=1,ans;i<=M;i++){ scanf("%d%d%d%d",&a,&b,&c,&d);if(a>b) swap(a,b); if(c>d) swap(c,d);ans=binary_ans(1,min(d-c+1,b-a+1),a,b,c,d,N);printf("%d\n",ans);} return 0;
}

转载于:https://www.cnblogs.com/zj75211/p/7978815.html

●BZOJ 4556 [Tjoi2016Heoi2016]字符串相关推荐

  1. [BZOJ4556][Tjoi2016Heoi2016]字符串 主席树+二分+倍增+后缀自动机

    4556: [Tjoi2016&Heoi2016]字符串 Time Limit: 20 Sec  Memory Limit: 128 MB Submit: 1215  Solved: 484 ...

  2. [BZOJ4556][TJOI2016HEOI2016]字符串(二分答案+后缀数组+RMQ+主席树)

    4556: [Tjoi2016&Heoi2016]字符串 Time Limit: 20 Sec  Memory Limit: 128 MB Submit: 1360  Solved: 545 ...

  3. BZOJ 1856: [Scoi2010]字符串 [Catalan数]

    1856: [Scoi2010]字符串 Time Limit: 5 Sec  Memory Limit: 64 MB Submit: 1418  Solved: 790 [Submit][Status ...

  4. bzoj#4555. [Tjoi2016Heoi2016]求和

    bzoj#4555. [Tjoi2016&Heoi2016]求和 题目描述 Solution 有一个关于第二类斯特林数的公式: {nm}=1m!∑i(mk)(m−k)n(−1)k\left\{ ...

  5. BZOJ 1090: [SCOI2003]字符串折叠 区间DP

    1090: [SCOI2003]字符串折叠 Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/p ...

  6. bzoj 1856: [Scoi2010]字符串(卡特兰数)

    1856: [Scoi2010]字符串 Time Limit: 5 Sec  Memory Limit: 64 MB Submit: 1604  Solved: 904 [Submit][Status ...

  7. BZOJ 1090: [SCOI2003]字符串折叠

    Time Limit: 10 Sec Memory Limit: 162 MB Submit: 1916 Solved: 1257 [Submit][Status][Discuss] Descript ...

  8. Bzoj4556 [Tjoi2016Heoi2016]字符串

    Time Limit: 20 Sec  Memory Limit: 128 MB Submit: 846  Solved: 327 Description 佳媛姐姐过生日的时候,她的小伙伴从某东上买了 ...

  9. BZOJ P4554 [Tjoi2016Heoi2016]游戏

    BZOJ P4554 [Tjoi2016&Heoi2016]游戏 题目 Description 在2016年,佳缘姐姐喜欢上了一款游戏,叫做泡泡堂.简单的说,这个游戏就是在一张地图上放上若干个 ...

最新文章

  1. iOS开发之--Masonry多个平均布局
  2. nginx limit_rate突然限速失败
  3. mysql支持UUID做外键_多表外键下将普通的id主键更新为uuid主键
  4. Deep Learning – Review by LeCun, Bengio, and Hinton
  5. DFS实现floodfill算法
  6. 城市大轰炸++(洛谷P1847题题解,Java语言描述)
  7. android 生命周期流程图,Android Studio ——Service的生命周期
  8. matlab 运行 释放内存,怎么能释放已经使用的内存
  9. Android Studio 4.0 / 4.0.1 无法创建Activity 问题
  10. 有人提到田英章欧体田字格范本,说两句。
  11. uni-app详情页开发
  12. 计算机主机房净高,机房建设标准
  13. 二维数组传参(二维数组作为函数参数)
  14. 英文论文评审意见_英文论文审稿意见汇总
  15. win下装django
  16. python音频 降噪_python - 使用pyaudio对音频播放进行降噪 - 堆栈内存溢出
  17. Postgresql 配置文件详解
  18. 中小型企业需用什么样的生产加工管理软件?
  19. tk.mybatis的批量插入扩展
  20. 网络管理之网络状态测试命令

热门文章

  1. centos java发送邮件发不出去_传真机发不出传真怎么办 传真机发不出传真解决方法【详解】...
  2. java二维码生成并可以转换
  3. android usb host hid,Android USB Host与HID通讯
  4. Hadoop学习(source方式安装篇)
  5. edittext怎么输入默认内容覆盖_Linux Shell 输入与输出重定向
  6. chrome浏览器无法上网_低调使用,内置特殊功能的浏览器。。
  7. Centos部署YApi
  8. 动态壁纸安卓_安卓 高清 动态 壁纸
  9. Spark SQL之jdbc方式访问
  10. 牛逼!Python的类和对象(长文系列第⑤篇)