BZOJ_3879_SvT_后缀数组+单调栈
BZOJ_3879_SvT_后缀数组+单调栈
Description
(我并不想告诉你题目名字是什么鬼)
有一个长度为n的仅包含小写字母的字符串S,下标范围为[1,n].
现在有若干组询问,对于每一个询问,我们给出若干个后缀(以其在S中出现的起始位置来表示),求这些后缀两两之间的LCP(LongestCommonPrefix)的长度之和.一对后缀之间的LCP长度仅统计一遍.
Input
第一行两个正整数n,m,分别表示S的长度以及询问的次数.
接下来一行有一个字符串S.
接下来有m组询问,对于每一组询问,均按照以下格式在一行内给出:
首先是一个整数t,表示共有多少个后缀.接下来t个整数分别表示t个后缀在字符串S中的出现位置.
Output
Sample Input
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_后缀数组+单调栈的更多相关文章
- 【BZOJ-3238】差异 后缀数组 + 单调栈
3238: [Ahoi2013]差异 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 1561 Solved: 734[Submit][Status] ...
- BZOJ_3238_[Ahoi2013]差异_后缀数组+单调栈
BZOJ_3238_[Ahoi2013]差异_后缀数组+单调栈 Description Input 一行,一个字符串S Output 一行,一个整数,表示所求值 Sample Input cacao ...
- BZOJ.4199.[NOI2015]品酒大会(后缀数组 单调栈)
BZOJ 洛谷 后缀自动机做法. 洛谷上SAM比SA慢...BZOJ SAM却能快近一倍... 显然只需要考虑极长的相同子串的贡献,然后求后缀和/后缀\(\max\)就可以了. 对于相同子串,我们能想 ...
- 【BZOJ3879】SvT 后缀数组+单调栈
[BZOJ3879]SvT Description (我并不想告诉你题目名字是什么鬼) 有一个长度为n的仅包含小写字母的字符串S,下标范围为[1,n]. 现在有若干组询问,对于每一个询问,我们给出若干 ...
- BZOJ3238 [Ahoi2013]差异 【后缀数组 + 单调栈】
题目链接 BZOJ3238 题解 简单题 经典后缀数组 + 单调栈套路,求所有后缀\(lcp\) #include<iostream> #include<cstdio> #in ...
- BZOJ4199 [Noi2015]品酒大会 【后缀数组 + 单调栈 + ST表】
题目 一年一度的"幻影阁夏日品酒大会"隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发"首席品 酒家"和"首席猎手"两个奖项,吸 ...
- poj 3415 Common Substrings 后缀数组+单调栈
题目链接 题意:求解两个字符串长度 大于等于k的所有相同子串对有多少个,子串可以相同,只要位置不同即可:两个字符串的长度不超过1e5; 如 s1 = "xx" 和 s2 = &qu ...
- poj 3415 Common Substrings(后缀数组+单调栈)
http://poj.org/problem?id=3415 Common Substrings Time Limit: 5000MS Memory Limit: 65536K Total Sub ...
- [BZOJ 3238] [AHOI 2013] 差异 【后缀数组 + 单调栈】
题目链接:BZOJ - 3238 题目分析 显然,这道题就是求任意两个后缀之间的LCP的和,这与后缀数组的联系十分明显. 求出后缀数组后,求出字典序相邻两个后缀的LCP,即 Height 数组. 那么 ...
随机推荐
- Angular v6 正式发布
Angular 6 正式发布 Angular 6 已经正式发布了!这个主要版本并不关注于底层的框架,更多地关注于工具链,以及使 Angular 在未来更容易快速推进. 作为发布的一部分,我们同步了主要 ...
- .net中的各种委托(Delegate、Action、Func)
1.Delegate,委托的鼻祖 protected delegate int ClassDelegate(int x, int y);//定义委托类型及参数 static void Main(str ...
- java -- 对Map按键排序、按值排序
java -- 对Map按键.按值排序 1.按键排序(sort by key) 直接上代码 ↓ public Map<String, Str ...
- 关于非现场审计软件的一些介绍(ACL、IEDA、Teammate)
http://group.vsharing.com/Article.aspx?aid=661512 IDEA是由caseware开发的数据分析软件.caseware的网址如下:http://www.c ...
- 了解与建设有中国特色的Android M&N(Android6.0和7.0新特性分析)
http://geek.csdn.NET/news/detail/110434 Android N已经发布有段时间,甚至马上都要发布android 7.1,相信不少玩机爱好者已经刷入最新的Androi ...
- AngularJS数据绑定中数据监控的机制说明
from : http://docs.angularjs.org/guide/scope When the browser calls into JavaScript the code execute ...
- 模仿天猫实战【SSM】——总结
第一篇文章链接:模仿天猫实战[SSM版]--项目起步 第二篇文章链接:模仿天猫实战[SSM版]--后台开发 总结:项目从4-27号开始写,到今天5-7号才算真正的完工,有许多粗糙的地方,但总算完成了, ...
- Java自学教程视频
BAT大咖助力 全面升级Android面试 BAT大牛亲授 基于ElasticSearch的搜房网实战 从天气项目看Spring Cloud微服务治理 Java企业级电商项目架构演进之路 Tomca ...
- DUIR Framework 相关技术介绍
开发者在搭建界面自动化测试框架时,又或者在开发界面自动化控制的机器人时,往往需要对界面进行自动化的程序控制.而现在公司内部使用的杜尔自动化框架,就是一个封装了界面自动化控制逻辑的程序框架.基于该框架, ...
- ajax 原生态和jquery封装区别
一.原生态 var xmlHttp = false; try{ if( xmlHttp && xmlHttp.readyState != 0 ){ xmlHttp.abort(); } ...