BZOJ4556 [Tjoi2016&Heoi2016]字符串
来源:互联网 发布:学哪种编程语言好? 编辑:程序博客网 时间:2024/05/16 23:56
恩,我们进行一些瞎YY,首先询问s[a~b]的所有子串与S[c~d]的最长LCP其实相当于询问s[a~b]的所有后缀与s[c~d]的最长LCP与这个子串的长度还有c~d的长度取min
进一步转化设suf[i]表示S的从第i个字符开始的后缀,则其实相当于询问这个
可以把d-c+1提到外面,就变成
这样只需要考虑左面的,考虑若答案为l(l<=d-c+1),则作为答案的后缀不可能取在i>b-l+1的位置,而在a<=i<=b-l+1的范围内,只要LCP(suf[i],suf[c])>=l,那么s[i~b]就是一个与s[c~d]有长度为l的LCP的子串
这样我们可以在<=d-c+1的范围内二分答案,每次只要判断a<=i<=b-mid+1的范围内是否存在LCP(suf[i],suf[c])>=mid即可,这个判断可以先建一颗后缀树,在后缀树上倍增找到suf[c]的最浅的长度>=mid的祖先,然后判断这个祖先的子树内是否有a<=i<=b-mid+1的后缀即可,这个可以用主席树
复杂度 O(m log^2 n)
#include<iostream>#include<cstdlib>#include<cstdio>#include<cstring>#include<cmath>#include<ctime>#include<algorithm>#include<iomanip>#include<vector>#include<stack>#include<queue>#include<map>#include<set>#include<bitset>using namespace std;#define MAXN 200010#define MAXM 4000010#define ll long long#define INF 1000000000#define MOD 1000000007#define eps 1e-8struct vec{int to;int fro;};int fa[MAXN],son[MAXN][26],mx[MAXN];int rt,lst,tot;int n,m;char s[MAXN];int Son[MAXM][2],Siz[MAXM];int Tot;int Rt[MAXN];vec mp[MAXN];int tai[MAXN],cnt;int dfn[MAXN],ndf[MAXN],siz[MAXN],tim;int Fa[MAXN][20];int dep[MAXN];int P[MAXN];vector<int>tp[MAXN];inline void be(int x,int y){mp[++cnt].to=y;mp[cnt].fro=tai[x];tai[x]=cnt;}void ins(int x){int np=++tot,p=lst;mx[np]=mx[p]+1;while(p&&!son[p][x]){son[p][x]=np;p=fa[p];}if(!p){fa[np]=rt;}else{int q=son[p][x];if(mx[q]==mx[p]+1){fa[np]=q;}else{int nq=++tot;mx[nq]=mx[p]+1;memcpy(son[nq],son[q],sizeof(son[q]));fa[nq]=fa[q];fa[np]=fa[q]=nq;while(p&&son[p][x]==q){son[p][x]=nq;p=fa[p];}}}lst=np;}void dfs(int x){int i,j,t,y;dfn[x]=++tim;ndf[tim]=x;siz[x]=1;dep[x]=dep[Fa[x][1]]+1;for(i=tai[x];i;i=mp[i].fro){y=mp[i].to;for(t=x,j=1;t;j++){Fa[y][j]=t;t=Fa[t][j];}dfs(y);siz[x]+=siz[y];}}void change(int &x,int xx,int l,int r,int p){x=++Tot;memcpy(Son[x],Son[xx],sizeof(Son[x]));Siz[x]=Siz[xx]+1;if(l==r){return ;}int mid=l+r>>1;if(p<=mid){change(Son[x][0],Son[xx][0],l,mid,p);}else{change(Son[x][1],Son[xx][1],mid+1,r,p);}}int anc(int x,int y){int i;for(i=19;i;i--){if(mx[Fa[x][i]]>=y){x=Fa[x][i];}}return x;}int ask(int x,int xx,int y,int z,int l,int r){if(y==l&&z==r){return Siz[xx]-Siz[x];}int mid=y+z>>1;if(r<=mid){return ask(Son[x][0],Son[xx][0],y,mid,l,r);}else if(l>mid){return ask(Son[x][1],Son[xx][1],mid+1,z,l,r);}else{return ask(Son[x][0],Son[xx][0],y,mid,l,mid)+ask(Son[x][1],Son[xx][1],mid+1,z,mid+1,r);}}bool OK(int x,int y,int z){return ask(Rt[dfn[x]-1],Rt[dfn[x]+siz[x]-1],1,n,y,z);}int main(){lst=rt=tot=1;int i,j,x,y,xx,yy;scanf("%d%d",&n,&m);scanf("%s",s+1);int p=rt;for(i=n;i;i--){ins(s[i]-'a');p=son[p][s[i]-'a'];P[i]=p;tp[P[i]].push_back(i);}for(i=2;i<=tot;i++){be(fa[i],i);}dfs(1);for(i=1;i<=tim;i++){Rt[i]=Rt[i-1];for(j=0;j<tp[ndf[i]].size();j++){change(Rt[i],Rt[i],1,n,tp[ndf[i]][j]);}}while(m--){scanf("%d%d%d%d",&x,&y,&xx,&yy);int l=1,r=min(yy-xx+1,y-x+1);int ans=0;while(l<=r){int mid=l+r>>1;if(OK(anc(P[xx],mid),x,y-mid+1)){ans=mid;l=mid+1;}else{r=mid-1;}}printf("%d\n",ans);}return 0;}/*8 1ababcabc1 3 6 8*/
0 0
- BZOJ4556: [Tjoi2016&Heoi2016]字符串
- Bzoj4556: [Tjoi2016&Heoi2016]字符串
- BZOJ4556 [Tjoi2016&Heoi2016]字符串
- bzoj4556【TJOI2016&HEOI2016】字符串
- BZOJ4556: [Tjoi2016&Heoi2016]字符串
- [bzoj4556][Tjoi2016&Heoi2016]字符串
- [bzoj4556][TJOI&&HEOI2016]字符串
- [BZOJ4556][Tjoi2016&Heoi2016]字符串(后缀数组+二分+st表+主席树)
- BZOJ4556:[Tjoi2016&Heoi2016]字符串 (后缀自动机+树上倍增+二分答案+线段树合并)
- 4556: [Tjoi2016&Heoi2016]字符串
- [Tjoi2016&Heoi2016]字符串
- JZOJ4614. 【TJOI2016&HEOI2016】字符串
- 【TJOI2016&&HEOI2016】字符串
- 4556: [Tjoi2016&Heoi2016]字符串
- 4556: [Tjoi2016&Heoi2016]字符串
- 【TJOI&HEOI2016】bzoj4556 字符串【解法一】
- 【TJOI&HEOI2016】bzoj4556 字符串【解法二】
- BZOJ 4556 [Tjoi2016&Heoi2016]字符串
- 有赞分层自动化测试实践
- DES加密 个人使用之后的
- Base64
- json-lib 的maven dependency
- PL/SQL基础篇
- BZOJ4556 [Tjoi2016&Heoi2016]字符串
- 标准JDBC连接
- java开发中常用的设计模式
- Python 计划
- 快捷键汇总(VS2013,PHP,MyEclipse,Java)
- Listview添加完HeaderView或者FooterView后,点击相应的view出现IndexOutOfBoundsException问题修复
- Android 学习思路
- hbase配置哈环境时遇到的问题
- 使用listview中一些问题-点击条目问题-设置背景问题-设置分割线问题