[后缀数组+二分+rmq] hdu 5008 Boring String Problem
来源:互联网 发布:c语言流程图生成器 编辑:程序博客网 时间:2024/04/26 07:30
有点小可惜这道题,当时整个思路都想到了,就是最后找最左下标的时候不会处理,
然后结束完发现直接暴力就可以了,想到了可是不敢写,10w个a直接就T了啊。。。
数据太弱了,敢写就过系列啊 T T。
然后希望有大神提供完美思路!
题意:
给一个字符串 然后n次询问
对于每一次询问给一个v
然后问第 l⊕r⊕v+1小的子串的区间 (⊕代表异或)
然后输出l r
这里的l r 就是上一次输出的l r 初始化是0 0
不存在输出0 0 如果多个 输出出现最早的。
对于每一次询问给一个v
然后问第 l⊕r⊕v+1小的子串的区间 (⊕代表异或)
然后输出l r
这里的l r 就是上一次输出的l r 初始化是0 0
不存在输出0 0 如果多个 输出出现最早的。
思路:
首先后缀数组就不说了,做完之后遍历height,没有重复的串的话,同一sa里面不同的长度就是排序了,小的在前。
所以开一个结构体ans存三个东西,l:初始位置,r:可用的第一个位置(因为会有重复的子串),s:这个下标内有多少名。
(声明:这里面的出现的不一定是最早的下标)
所以我们先通过二分 找到它是在哪个后缀的前缀,就是sa的下标。
然后通过暴力前后,rmq判断,找到最早出现的位置(就是这个 居然不超时!!)
代码:
#include"cstdlib"#include"cstdio"#include"cstring"#include"cmath"#include"stack"#include"algorithm"#include"iostream"using namespace std;#define N 300012__int64 wa[N],wb[N],wv[N],wws[N];__int64 sa[N],ra[N],v[N],height[N],used[N];__int64 Log[N],dp[N][30];char fuck[N],fu[N];struct node{ __int64 l,r,s;} ans[N];__int64 cmp(__int64 *r,__int64 a,__int64 b,__int64 l){ return r[a]==r[b]&&r[a+l]==r[b+l];}void da(__int64 n,__int64 m){ __int64 i,j,p,*x=wa,*y=wb; for(i=0; i<m; i++) wws[i]=0; for(i=0; i<n; i++) wws[x[i]=v[i]]++; for(i=1; i<m; i++) wws[i]+=wws[i-1]; for(i=n-1; i>=0; i--) sa[--wws[x[i]]]=i; for(j=1,p=1; p<n; j*=2,m=p) { for(i=n-j,p=0; i<n; i++) y[p++]=i; for(i=0; i<n; i++) if(sa[i]>=j) y[p++]=sa[i]-j; for(i=0; i<n; i++) wv[i]=x[y[i]]; for(i=0; i<m; i++) wws[i]=0; for(i=0; i<n; i++) wws[wv[i]]++; for(i=1; i<m; i++) wws[i]+=wws[i-1]; for(i=n-1; i>=0; i--) sa[--wws[wv[i]]]=y[i]; for(swap(x,y),p=1,i=1,x[sa[0]]=0; i<n; i++) x[sa[i]]=cmp(y,sa[i],sa[i-1],j)?p-1:p++; } return ;}void gethei(__int64 n){ __int64 i,j,k=0; for(i=1; i<=n; i++) ra[sa[i]]=i; for(i=0; i<n; i++) { if(k) k--; j=sa[ra[i]-1]; while(v[i+k]==v[j+k]) k++; height[ra[i]]=k; } return ;}void rmqinit(__int64 n){ __int64 i,j; __int64 m=Log[n]; for(i=1; i<=n; i++) dp[i][0]=height[i]; for(i=1; i<=m; i++) { for(j=1; j+(1<<i)-1<=n; j++) dp[j][i]=min(dp[j][i-1],dp[j+(1<<(i-1))][i-1]); }}__int64 lcp(__int64 a,__int64 b){ __int64 x=ra[a],y=ra[b]; if(x>y) swap(x,y); x++; __int64 m=Log[y-x+1]; return min(dp[x][m],dp[y-(1<<m)+1][m]);}int main(){ Log[0]=-1; for(int i=1; i<=N; i++) Log[i]=(i&(i-1))?Log[i-1]:Log[i-1]+1; while(scanf("%s",fuck)!=-1) { __int64 n; scanf("%I64d",&n); __int64 i; __int64 len=strlen(fuck); for(i=0; i<len; i++) v[i]=fuck[i]-'a'+2; v[len]=0; da(len+1,40); gethei(len); rmqinit(len); memset(ans,0,sizeof(ans)); for(i=1; i<=len; i++) { ans[i].l=sa[i]; // 初始位置,原串的下标 ans[i].r=sa[i]+height[i]; //可用的第一个位置 也就是去重了 ans[i].s=len-sa[i]-height[i]+ans[i-1].s; // 到i 已经有多少名了 } __int64 ansl,ansr; //输出答案 初始化0 ansl=ansr=0; while(n--) { __int64 xx; __int64 k,sb=-1,l,r,chang; scanf("%I64d",&xx); k=(ansl^ansr^xx)+1; //记得异或完加一 if(k>ans[len].s) //如果超出 说明不存在 直接输出 { puts("0 0"); ansl=ansr=0; continue; } l=1; r=len; while(l<=r) //二分位置 { __int64 mid=(l+r)/2; if(ans[mid].s>=k) { sb=mid; r=mid-1; } else l=mid+1; } ansl=ans[sb].l; ansr=ans[sb].r+(k-ans[sb-1].s-1); chang=ansr-ansl+1; //[ansl,ansr]就是子串了 但不一定是最早的,同时记录长度 __int64 x; x=sb-1; //向前遍历 while(x>=2 && lcp(sa[sb],sa[x])>=chang) { ansl=min(ansl,ans[x].l); //记录最小 x--; } x=sb+1; //向后遍历 while(x<=len && lcp(sa[sb],sa[x])>=chang) { ansl=min(ansl,ans[x].l); //记录最小 x++; } ansl=ansl+1; ansr=ansl+chang-1; printf("%I64d %I64d\n",ansl,ansr); } } return 0;}
0 0
- [后缀数组+二分+rmq] hdu 5008 Boring String Problem
- HDU - 5008 Boring String Problem (后缀数组+二分+RMQ)
- HDU 5008 Boring String Problem 后缀数组 RMQ
- HDU 5008 Boring String Problem 二分 + 后缀数组
- hdu5008 Boring String Problem 后缀数组+二分+RMQ
- hdu 5008 Boring String Problem(后缀数组)
- HDU 5008 Boring String Problem 后缀数组
- hdu 5008 Boring String Problem(后缀数组)
- hdu 5008 Boring String Problem 【后缀数组】
- hdu 5008 Boring String Problem 后缀数组
- HDU 5008 Boring String Problem 后缀数组
- hdu5008 Boring String Problem 后缀数组+二分
- hdu 5008(2014 ACM/ICPC Asia Regional Xi'an Online ) Boring String Problem(后缀数组&二分)
- 【后缀数组】 HDOJ 5008 Boring String Problem
- hdu 5008 Boring String Problem(后缀自动机构造后缀树)
- hdu 5008 (后缀数组 + rmq +二分)
- hdu5008 Boring String Problem,2014西安网络赛B题,后缀数组,RMQ
- hdu5008-Boring String Problem(后缀数组专题)
- 一个hdmi音频问题的debug
- GitHub入门教程(二)- 使用前的配置
- sizeof的详尽计算结构体字节数方法
- ios 图片处理
- 服务器jsp推送
- [后缀数组+二分+rmq] hdu 5008 Boring String Problem
- WF-Mailer Fails to Send Email Notifications after cloning
- 获取window服务路径
- 【工具】MQ常用命令
- 关于spring中HibernateTransactionManager和DataSourceTransactionManager
- [GEiv]第五章:个体集群 虚假的分配与释放
- 使用gcd_ wait来 处理gcd
- Netty的几个要点
- 花生壳内网穿透、nat123映射p2p穿透,都是如何穿透的