[bzoj3879]SvT
来源:互联网 发布:网络建设与管理答案 编辑:程序博客网 时间:2024/06/05 09:14
3879: SvT
Time Limit: 30 Sec Memory Limit: 512 MB
Submit: 236 Solved: 84
[Submit][Status][Discuss]
Description
(我并不想告诉你题目名字是什么鬼)
有一个长度为n的仅包含小写字母的字符串S,下标范围为[1,n].
现在有若干组询问,对于每一个询问,我们给出若干个后缀(以其在S中出现的起始位置来表示),求这些后缀两两之间的LCP(LongestCommonPrefix)的长度之和.一对后缀之间的LCP长度仅统计一遍.
Input
第一行两个正整数n,m,分别表示S的长度以及询问的次数.
接下来一行有一个字符串S.
接下来有m组询问,对于每一组询问,均按照以下格式在一行内给出:
首先是一个整数t,表示共有多少个后缀.接下来t个整数分别表示t个后缀在字符串S中的出现位置.
Output
对于每一组询问,输出一行一个整数,表示该组询问的答案.由于答案可能很大,仅需要输出这个答案对于23333333333333333(一个巨大的质数)取模的余数.
Sample Input
7 3popoqqq1 42 3 54 1 2 5 6
Sample Output
002
Hint
样例解释:
对于询问一,只有一个后缀
对于询问二,有两个后缀
对于询问三,有四个后缀
对于
特别注意:由于另一世界线的某些参数发生了变化,对于一组询问,即使一个后缀出现了多次,也仅算一次.
对于每一个询问,按照rank排序,然后从小到大求出每一对
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define LL long long #define Mod 23333333333333333const int N=500010;const int M=3000010;char s[N];int n,m,T,now[M],stack[N],top,l[N],r[N],t1[N],t2[N],c[N],sa[N],height[N],rank[N],st[N][20],Log[N],use[M];inline int in(){ int x=0;char ch=getchar(); while(ch<'0'||ch>'9') ch=getchar(); while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); return x;}inline bool cmp(int *y,int p,int q,int k){ int o1,o2; o1=p+k>=n?-1:y[p+k]; o2=q+k>=n?-1:y[q+k]; return o1==o2&&y[p]==y[q];}inline void build_sa(){ int i,k,p,*x=t1,*y=t2; for(m=26,i=0;i<m;++i) c[i]=0; for(i=0;i<n;++i) ++c[x[i]=s[i]-'a']; for(i=1;i<m;++i) c[i]+=c[i-1]; for(i=n-1;~i;--i) sa[--c[x[i]]]=i; for(k=1;k<=n;k<<=1){ for(p=0,i=n-k;i<n;++i) y[p++]=i; for(i=0;i<n;++i) if(sa[i]>=k) y[p++]=sa[i]-k; for(i=0;i<m;++i) c[i]=0; for(i=0;i<n;++i) ++c[x[y[i]]]; for(i=1;i<m;++i) c[i]+=c[i-1]; for(i=n-1;~i;--i) sa[--c[x[y[i]]]]=y[i]; swap(x,y); x[sa[0]]=0;m=1; for(i=1;i<n;++i) x[sa[i]]=cmp(y,sa[i],sa[i-1],k)?m-1:m++; if(m>=n) break; }}inline void build_height(){ int i,j,k=0; for(i=0;i<n;++i) rank[sa[i]]=i; for(i=0;i<n;++i){ if(!rank[i]) continue; k=k?--k:k; j=sa[rank[i]-1]; while(s[i+k]==s[j+k]) ++k; height[rank[i]]=k; } /*------------st------------*/ memset(st,127/3,sizeof(st)); for(i=0;i<n;++i) st[i][0]=height[i]; for(j=1;j<=20;++j) for(i=0;i+(1<<(j-1))<n;++i) st[i][j]=min(st[i][j-1],st[i+(1<<(j-1))][j-1]); for(j=0,i=1;i<=n;++i){ if((1<<(j+1))<=i) ++j; Log[i]=j; }}inline int LCP(int x,int y){ int k=Log[y-x];++x; return min(st[x][k],st[y-(1<<k)+1][k]); }int main(){ int i;; LL ans; n=in();T=in(); for(i=0;i<n;++i){ char ch=getchar(); while(ch<'a'||ch>'z') ch=getchar(); s[i]=ch; } build_sa(); build_height(); while(T--){ ans=0; m=in(); for(i=1;i<=m;++i) now[i]=in(); sort(now+1,now+m+1); m=unique(now+1,now+m+1)-now-1; for(i=1;i<=m;++i) now[i]=rank[now[i]-1]; sort(now+1,now+m+1); for(i=2;i<=m;++i){ int o=LCP(now[i-1],now[i]); use[i-2]=o; } --m;stack[top=1]=0; for(l[1]=0,i=1;i<m;++i){ while(top&&use[stack[top]]>use[i]) --top; l[i]=top?stack[top]+1:0; stack[++top]=i; } stack[top=1]=m-1; for(r[m-1]=m-1,i=m-2;i>=0;--i){ while(top&&use[stack[top]]>=use[i]) --top; r[i]=top?stack[top]-1:m-1; stack[++top]=i; } for(i=0;i<m;++i) ans=(ans+((LL)(i-l[i]+1)*(LL)(r[i]-i+1))%Mod*(LL)use[i]%Mod)%Mod; printf("%I64d\n",ans); for(i=0;i<=m;++i) use[i]=0; }}
- [BZOJ3879] SvT
- [bzoj3879]SvT
- BZOJ3879 SvT
- bzoj3879 SvT
- bzoj3879: SvT 后缀自动机
- 【BZOJ3879】SvT 后缀树+虚树
- BZOJ3879: SvT 后缀树 虚树
- [BZOJ3879]SvT(后缀数组+单调栈)
- BZOJ3879:SvT(后缀自动机+虚树)
- bzoj3879 SvT(后缀数组+单调栈)
- 【BZOJ3879】SvT,后缀数组+单调栈维护sum
- bzoj3879
- SVT
- 3879: SvT
- bzoj 3879 SvT
- bzoj 3879: SvT
- 矩阵填充的SVT算法
- UT-IT-ST-BBIT-SDV-SIT-SVT
- 如何让Oracle客户端显示中文
- postgresql更新序列的起始值
- sql中sum()和count()的区别
- 我们应该知道的java位运算
- Activiti源码浅析:Activiti的活动授权机制
- [bzoj3879]SvT
- ZZULI 1863: 神の数【模拟】
- VS 2013 中MFC程序编译过程出现 RC2108错误
- iOS网络编程3--swift中使用AFNetworking库
- LeetCode 59 Spiral Matrix II
- 实现winfrom进度条及进度信息提示,winfrom程序假死处理
- android AsyncTask介绍
- RecyclerView的简单使用,实现下拉刷新、上拉加载
- 搜索引擎选型调研文档