BZOJ_3879_SvT_后缀数组+单调栈

Description

(我并不想告诉你题目名字是什么鬼)

有一个长度为n的仅包含小写字母的字符串S,下标范围为[1,n].

现在有若干组询问,对于每一个询问,我们给出若干个后缀(以其在S中出现的起始位置来表示),求这些后缀两两之间的LCP(LongestCommonPrefix)的长度之和.一对后缀之间的LCP长度仅统计一遍.

Input

第一行两个正整数n,m,分别表示S的长度以及询问的次数.

接下来一行有一个字符串S.

接下来有m组询问,对于每一组询问,均按照以下格式在一行内给出:

首先是一个整数t,表示共有多少个后缀.接下来t个整数分别表示t个后缀在字符串S中的出现位置.

Output

对于每一组询问,输出一行一个整数,表示该组询问的答案.由于答案可能很大,仅需要输出这个答案对于23333333333333333(一个巨大的质数)取模的余数.
 

Sample Input

7 3
popoqqq
1 4
2 3 5
4 1 2 5 6

Sample Output

0
0
2


类似http://www.cnblogs.com/suika/p/8995997.html这道题,只不过本题变成了给定多个后缀的LCP。

先求出height数组,然后建立ST,设g[i]表示给出的第i个后缀到第i+1个后缀的LCP长度。

转化为求所有区间最小值之和。

dp[i]表示以第i个位置为结尾的所有区间最小值之和,对于i左边第一个大于等于g[i]的g[j],有f[i]=f[j]+(i-j)*g[i],答案就是dp[i]之和。

代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define RR register
__attribute__((optimize("-O2")))inline char nc() {
static char buf[100000],*p1,*p2;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
__attribute__((optimize("-O2")))inline int rd() {
int x=0; RR char c=nc();
while(c<'0'||c>'9') c=nc();
while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-'0',c=nc();
return x;
}
__attribute__((optimize("-O2")))inline int rc() {
char c=nc();
while(c<'a'||c>'z') c=nc();
return (int)c;
}
#define N 500050
typedef long long ll;
int n,m,wa[N],wb[N],wv[N],sa[N],height[N],rank[N],r[N],ws[N];
char ch[N];
int f[21][N],L[N],vis[N],s[N],g[N];
int v[3000050],Q[3000050];
ll dp[N];
__attribute__((optimize("-O2")))void build_sa_array() {
m=27;
int i,j,p,*x=wa,*y=wb,*t;
for(i=0;i<m;i++) ws[i]=0;
for(i=0;i<n;i++) ws[x[i]=r[i]]++;
for(i=1;i<m;i++) ws[i]+=ws[i-1];
for(i=n-1;i>=0;i--) sa[--ws[x[i]]]=i;
for(p=j=1;p<n;j<<=1,m=p) {
for(p=0,i=n-j;i<n;i++) y[p++]=i;
for(i=0;i<n;i++) if(sa[i]-j>=0) y[p++]=sa[i]-j;
for(i=0;i<n;i++) wv[i]=x[y[i]];
for(i=0;i<m;i++) ws[i]=0;
for(i=0;i<n;i++) ws[wv[i]]++;
for(i=1;i<m;i++) ws[i]+=ws[i-1];
for(i=n-1;i>=0;i--) sa[--ws[wv[i]]]=y[i];
for(t=x,x=y,y=t,i=p=1,x[sa[0]]=0;i<n;i++) {
if(y[sa[i]]==y[sa[i-1]]&&y[sa[i]+j]==y[sa[i-1]+j]) x[sa[i]]=p-1;
else x[sa[i]]=p++;
}
}
for(i=1;i<n;i++) rank[sa[i]]=i;
for(i=p=0;i<n-1;height[rank[i++]]=p)
for(p?p--:0,j=sa[rank[i]-1];r[i+p]==r[j+p];p++);
}
__attribute__((optimize("-O2")))int get_min(int l,int r) {
int len=L[r-l+1];
return min(f[len][l],f[len][r-(1<<len)+1]);
}
__attribute__((optimize("-O2")))void ST() {
int i,j;
for(i=2;i<=n;i++) L[i]=L[i>>1]+1;
for(i=1;i<=n;i++) f[0][i]=height[i];
for(i=1;(1<<i)<=n;i++) {
for(j=1;j+(1<<i)-1<=n;j++) {
f[i][j]=min(f[i-1][j],f[i-1][j+(1<<(i-1))]);
}
}
}
__attribute__((optimize("-O2")))bool cmp(int x,int y) {
return rank[x]<rank[y];
}
char pbuf[10000000] , *pp = pbuf;
__attribute__((optimize("-O2")))void write(int x)
{
static int sta[35];
int top = 0;
if(!x)sta[++top]=0;
while(x) sta[++top] = x % 10 , x /= 10;
while(top) *pp ++ = sta[top -- ] ^ '0';
}
__attribute__((optimize("-O2")))int main() {
int T;
n=rd(); T=rd();
RR int i;
for(i=0;i<n;i++) r[i]=rc()-'a'+1;
r[n++]=0;
int tot=0;
build_sa_array(); n--; ST();
while(T--) {
tot++;
int t=0;
v[0]=rd();
RR int j;
for(j=1;j<=v[0];j++) {
v[j]=rd();
v[j]--;
if(vis[v[j]]==tot) {
j--; v[0]--;
}
vis[v[j]]=tot;
}
sort(v+1,v+v[0]+1,cmp);
for(j=1;j<v[0];j++) {
g[j]=get_min(rank[v[j]]+1,rank[v[j+1]]);
}
t=1; Q[1]=0;
long long ans=0;
for(j=1;j<v[0];j++) {
while(t&&g[Q[t]]>g[j]) t--;
dp[j]=dp[Q[t]]+1ll*(j-Q[t])*g[j];
ans+=dp[j];
Q[++t]=j;
}
write(ans);*pp++='\n';
}
fwrite(pbuf , 1 , pp - pbuf , stdout);
}

BZOJ_3879_SvT_后缀数组+单调栈的更多相关文章

  1. 【BZOJ-3238】差异 后缀数组 + 单调栈

    3238: [Ahoi2013]差异 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 1561  Solved: 734[Submit][Status] ...

  2. BZOJ_3238_[Ahoi2013]差异_后缀数组+单调栈

    BZOJ_3238_[Ahoi2013]差异_后缀数组+单调栈 Description Input 一行,一个字符串S Output 一行,一个整数,表示所求值 Sample Input cacao ...

  3. BZOJ.4199.[NOI2015]品酒大会(后缀数组 单调栈)

    BZOJ 洛谷 后缀自动机做法. 洛谷上SAM比SA慢...BZOJ SAM却能快近一倍... 显然只需要考虑极长的相同子串的贡献,然后求后缀和/后缀\(\max\)就可以了. 对于相同子串,我们能想 ...

  4. 【BZOJ3879】SvT 后缀数组+单调栈

    [BZOJ3879]SvT Description (我并不想告诉你题目名字是什么鬼) 有一个长度为n的仅包含小写字母的字符串S,下标范围为[1,n]. 现在有若干组询问,对于每一个询问,我们给出若干 ...

  5. BZOJ3238 [Ahoi2013]差异 【后缀数组 + 单调栈】

    题目链接 BZOJ3238 题解 简单题 经典后缀数组 + 单调栈套路,求所有后缀\(lcp\) #include<iostream> #include<cstdio> #in ...

  6. BZOJ4199 [Noi2015]品酒大会 【后缀数组 + 单调栈 + ST表】

    题目 一年一度的"幻影阁夏日品酒大会"隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发"首席品 酒家"和"首席猎手"两个奖项,吸 ...

  7. poj 3415 Common Substrings 后缀数组+单调栈

    题目链接 题意:求解两个字符串长度 大于等于k的所有相同子串对有多少个,子串可以相同,只要位置不同即可:两个字符串的长度不超过1e5; 如 s1 = "xx" 和 s2 = &qu ...

  8. poj 3415 Common Substrings(后缀数组+单调栈)

    http://poj.org/problem?id=3415 Common Substrings Time Limit: 5000MS   Memory Limit: 65536K Total Sub ...

  9. [BZOJ 3238] [AHOI 2013] 差异 【后缀数组 + 单调栈】

    题目链接:BZOJ - 3238 题目分析 显然,这道题就是求任意两个后缀之间的LCP的和,这与后缀数组的联系十分明显. 求出后缀数组后,求出字典序相邻两个后缀的LCP,即 Height 数组. 那么 ...

随机推荐

  1. Java IO学习--(三)通道

    Java IO中的管道为运行在同一个JVM中的两个线程提供了通信的能力.所以管道也可以作为数据源以及目标媒介. 你不能利用管道与不同的JVM中的线程通信(不同的进程).在概念上,Java的管道不同于U ...

  2. angularjs学习笔记之一

    directive 通过AngularJS模块API中的.directive()方法,我们可以通过传入一个字符串和一个函数来 注册一个新指令.其中字符串是这个指令的名字,指令名应该是驼峰命名风格的,函 ...

  3. JasperReport的安装

    下载网址http://community.jaspersoft.com/community-download

  4. redis主从,哨兵回忆手册

    redis主从 持久化的开启与主从集群是否生效无关系 Slave Server同样是以非阻塞的方式完成数据同步.在同步期间,如果有客户端提交查询请求,Redis则返回同步之前的数据(注意初次同步则会阻 ...

  5. 只需几分钟跟小猫学前端(内含视频教程):nodejs基础之用express、ejs、mongdb建设简单的网站

    开门见山视频教程 https://v.qq.com/x/page/d0645s79xrq.html 前 言: 这是小猫的第二篇node教程,第一篇教程是一个简单的试水,小猫的node教程面向对象为没有 ...

  6. “Location of the Android SDK has not been set up in the preferences”问题的解决

    方法来源:http://stackoverflow.com/questions/5894929/location-of-the-Android-sdk-has-not-been-setup-in-th ...

  7. java线程之线程通信

    前面提到多线程操作会有一个资源共享问题. 日常生活中,对于一个超市,有供货商往超市运货,有消费者从超市取货,供货商和消费者都与超市 建立了某种连接,超市就相当于公共资源,而他们的这种行为放到线程上说就 ...

  8. asp.net MVC 框架中控制器里使用Newtonsoft.Json对前端传过来的字符串进行解析

    下面我用一个实例来和大家分享一下我的经验,asp.net MVC 框架中控制器里使用Newtonsoft.Json对前端传过来的字符串进行解析. using Newtonsoft.Json; usin ...

  9. 2018年,传言QQ首次被神秘黑客DDOS攻击,Python可以实现?

    于2018-5-10日晚 网络流传黑客DDOS攻击了QQ服务器,导致大家聊天发送内容时出现感叹号.我们都知道一般情况下出现感叹号都是你的网络不稳定,或者...别人已经删除你了.然而昨晚很奇怪,发出的内 ...

  10. ASP.NET(C#) Repeater分页的实现

    ASP.NET(C#) Repeater分页的实现 第一种方式: 数据库连接代码: using System; using System.Data; using System.Configuratio ...