bzoj 3230 相似子串
来源:互联网 发布:linux查看声卡驱动 编辑:程序博客网 时间:2024/06/08 18:35
3230: 相似子串
Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 1767 Solved: 438
[Submit][Status][Discuss]
Description
Input
输入第1行,包含3个整数N,Q。Q代表询问组数。
第2行是字符串S。
接下来Q行,每行两个整数i和j。(1≤i≤j)。
Output
输出共Q行,每行一个数表示每组询问的答案。如果不存在第i个子串或第j个子串,则输出-1。
Sample Input
5 3
ababa
3 5
5 9
8 10
ababa
3 5
5 9
8 10
Sample Output
18
16
-1
16
-1
HINT
样例解释
第1组询问:两个子串是“aba”,“ababa”。f = 32 + 32 = 18。
第2组询问:两个子串是“ababa”,“baba”。f = 02 + 42 = 16。
第3组询问:不存在第10个子串。输出-1。
数据范围
N≤100000,Q≤100000,字符串只由小写字母'a'~'z'组成
Source
后缀数组+二分+RMQ
【分析】
不得不说我已经把后缀数组的题写成黑箱题了...
又是一道手玩出来的题...
搞一个原串的后缀数组,再搞一个反串的...
分别搞一下lcp就行了...
不过我还是不太清楚为什么是lower_bound,总感觉是upper_bound-1才对啊...脑洞开了改了一下就A掉了...= =
以上的话当p处理...窝脑子water了...
【代码】
//bzoj 3230 相似子串#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#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=100005;int m,q;char s[mxn];ll cnt[mxn];ll sum,len,u,v;inline ll read(){ ll x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();} while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); return x*f;}struct node //大家好我是黑箱 { int st[mxn][30],rank[mxn],height[mxn]; int a[mxn],b[mxn],x[mxn],y[mxn],sa[mxn]; 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=128; 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++); } inline void init() { int i,j; fo(i,1,len) st[i][0]=height[i]; fo(j,1,28) 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 lcp(int x,int y) { if(x==y) return len-x+1; x=rank[x],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]); }}A,B;int main(){ int i,j,k; len=read(),q=read(); scanf("%s",s+1); fo(i,1,len) A.a[i]=s[i]; fo(i,1,len) B.a[i]=s[len-i+1]; A.work(),A.init(); B.work(),B.init(); sum=len*(len+1)/2; fo(i,1,len) sum-=A.height[i]; fo(i,1,len) cnt[i]=cnt[i-1]+len-A.sa[i]+1-A.height[i]; while(q--) { u=read(),v=read(); if(v>sum) { printf("-1\n"); continue; } int Tu=lower_bound(cnt+1,cnt+len+1,u)-cnt; int Tv=lower_bound(cnt+1,cnt+len+1,v)-cnt; int tu=u-cnt[Tu-1]+A.sa[Tu]+A.height[Tu]-1; int tv=v-cnt[Tv-1]+A.sa[Tv]+A.height[Tv]-1; ll start=min(A.lcp(A.sa[Tu],A.sa[Tv]),min(tu-A.sa[Tu]+1,tv-A.sa[Tv]+1)); ll end=min(B.lcp(len-tu+1,len-tv+1),min(tu-A.sa[Tu]+1,tv-A.sa[Tv]+1)); printf("%lld\n",start*start+end*end); } return 0;}
1 0
- bzoj 3230 相似子串
- BZOJ 3230 相似子串 后缀数组
- bzoj 3230 相似子串 后缀数组
- 【BZOJ 3230】相似子串 后缀数组
- BZOJ 3230 相似子串|后缀数组|RMQ
- bzoj 3230: 相似子串 (后缀数组+RMQ+二分)
- BZOJ 3230 相似子串 后缀数组+二分+ST表
- bzoj 3230: 相似子串 后缀数组+rmq+二分
- 相似子串 bzoj3230
- BZOJ3230 相似子串
- 【51Nod1753】相似子串
- BZOJ3230 相似子串 后缀自动机做法
- bzoj3230 相似子串(SA+lcp+二分)
- 51nod 1753 相似子串
- 51Nod-1753-相似子串
- [BZOJ 1396] 识别子串
- bzoj 1396 识别子串
- [BZOJ3230]相似子串(后缀数组+二分+st表)
- SpringMvc中返回Json数据的原理分析
- 软件性能测试
- 算法提高 聪明的美食家
- js鼠标事件实现便笺墙
- 写冒泡排序可以排序一个整型数组
- bzoj 3230 相似子串
- python sqlalchemy core
- Perl学习笔记整理
- android分辨率 尺寸 dpi换算
- 循环链表之双循环链表
- LeetCode 122. Best Time to Buy and Sell Stock II
- 在linux下用C写一个HelloWorld(GCC版)
- zoc for mac序列号
- ROC vs PRC