\(\\\)

Description


给出长度为 \(n\) 的一个字符串, \(m\) 次询问:

每次给出一个 \(t\) ,后面有 \(t\) 个数 \(x_i\) ,求
\[ \sum_{i,j\in [1,t],i\not =j} lcp(suf(x_i),suf(x_j)) \]

  • \(n\le 5\times 10^5,\sum t\le 3\times 10^6\)

\(\\\)

Solution


设 \(lcp(i,j)\) 表示 \(suf(i),suf(j)\) 的最长公共前缀长度,设 \(LCP(i,j)\) 表示 \(lcp(sa[i],sa[j])\) 。

有一个结论:\(\forall k\in[i,j]\ ,\ LCP(i,j)=\min\{LCP(i,k),LCP(k,j)\}\) 。

证明过程与求任意两后缀 \(lcp\) 相同。

\(\\\)

一个自然的想法是,按照 \(rank\) 将给出的后缀排序。

那么我们只需求出新序列相邻两后缀的 \(lcp\) ,然后剩下的都可以用这些长度取 \(min\) 去刻画了。

求新序列的相邻两后缀 \(lcp\) 可以用 \(height+RMQ\) 搞。

然后询问就变成,一个长度为 \(t-1\) 的序列,所有区间 \(min\) 的和。

做法同 [ AHOI 2013 ] 差异 一题,我和那题一样用的是一种特殊的单调栈,只需扫一遍。

\(\\\)

Code


#include<cmath>
#include<cctype>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define N 500010
#define M 3000010
#define R register
#define gc getchar
#define mod 23333333333333333ll
using namespace std;
typedef long long ll;inline ll rd(){ll x=0; bool f=0; char c=gc();while(!isdigit(c)){if(c=='-')f=1;c=gc();}while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=gc();}return f?-x:x;
}ll n,m,s[N],sa[N],t1[N],t2[N],rk[N],h[N],cnt[N];inline void da(ll n,ll m){s[n++]=0;ll *x=t1,*y=t2;for(R ll i=0;i<n;++i) ++cnt[x[i]=s[i]];for(R ll i=1;i<m;++i) cnt[i]+=cnt[i-1];for(R ll i=n-1;~i;--i) sa[--cnt[x[i]]]=i;for(R ll k=1,p=0;p<n&&k<=n;k<<=1,m=p){p=0;for(R ll i=n-k;i<n;++i) y[p++]=i;for(R ll i=0;i<n;++i) if(sa[i]>=k) y[p++]=sa[i]-k;for(R ll i=0;i<m;++i) cnt[i]=0;for(R ll i=0;i<n;++i) ++cnt[x[y[i]]];for(R ll i=1;i<m;++i) cnt[i]+=cnt[i-1];for(R ll i=n-1;~i;--i) sa[--cnt[x[y[i]]]]=y[i];swap(x,y); p=1; x[sa[0]]=0;for(R ll i=1;i<n;++i)x[sa[i]]=(y[sa[i]]==y[sa[i-1]]&&y[sa[i-1]+k]==y[sa[i]+k])?p-1:p++;}--n; h[0]=0;for(R ll i=0;i<n;++i) sa[i]=sa[i+1];for(R ll i=0;i<n;++i) rk[sa[i]]=i;for(R ll i=0,p=0;i<n;++i){if(!rk[i]) continue;if(p) --p;while(s[i+p]==s[sa[rk[i]-1]+p]) ++p;h[rk[i]]=p;}
}struct ST{ll c[N][20];inline void reset(){for(R ll i=0;i<n;++i) c[i][0]=h[i];for(R ll k=1;(1ll<<k)<=n;++k)for(R ll i=0;i<n-k;++i) c[i][k]=min(c[i][k-1],c[i+(1ll<<(k-1))][k-1]);}inline ll query(ll l,ll r){ll t=log2(r-l+1);return min(c[l][t],c[r-(1ll<<t)+1][t]);}
}st;ll c[M],sum,top;struct S{int x,cnt;}stk[M];inline bool cmp(ll x,ll y){return rk[x]<rk[y];}inline void work(){ll t=rd(),res=0;for(R int i=1;i<=t;++i) c[i]=rd()-1;sort(c+1,c+1+t);for(R int i=1,tmp=0;i<=t;++i){c[++tmp]=c[i];while(c[i+1]==c[i]&&i<=t) ++i;if(i==t){t=tmp;break;}}if(t<=1){puts("0");return;}sort(c+1,c+1+t,cmp);sum=top=0;for(R ll i=1,now,cnt=1;i<t;++i,cnt=1){now=st.query(rk[c[i]]+1,rk[c[i+1]]);while(top&&stk[top].x>=now){cnt+=stk[top].cnt;sum-=stk[top].cnt*stk[top].x;--top;}stk[++top].x=now;stk[top].cnt=cnt;(sum+=stk[top].x*stk[top].cnt)%=mod;(res+=sum)%=mod;}printf("%lld\n",res);
}int main(){n=rd(); m=rd();char c=gc(); while(!isalpha(c)) c=gc();s[0]=c-' ';for(R ll i=2;i<=n;++i) s[i-1]=gc()-' ';da(n,256); st.reset();while(m--) work();return 0;
}

转载于:https://www.cnblogs.com/SGCollin/p/9990170.html

[ BZOJ 3879 ] SvT相关推荐

  1. 【BZOJ 3879】SvT

    [链接]h在这里写链接 [题意]     给你一个长度为n的字符串以及m个询问.     每个询问询问你所给的一些后缀,所有任意两个后缀之间的lcp的总和;     n<=5*10^5     ...

  2. NOI数据结构:后缀树

    NOI数据结构:后缀树 后缀树_fanzitao的专栏-CSDN博客_后缀树 后缀树 - sangmado - 博客园 字符串-后缀树和后缀数组详解 字符串-后缀树和后缀数组详解_吴泽龙的博客-CSD ...

  3. 暑假集训 ---- 字符串2 (SAM专题)

    P1368 工艺 把串插入 S A M SAM SAM 插两次,然后贪心找最小字典序即可 [AHOI2013]差异 两个串的最长公共后缀就是后缀自动机上 lca 的长度 于是把两个串反过来,对于每一个 ...

  4. BZOJ.1558.[JSOI2009]等差数列(线段树 差分)

    BZOJ 洛谷 首先可以把原序列\(A_i\)转化成差分序列\(B_i\)去做. 这样对于区间加一个等差数列\((l,r,a_0,d)\),就可以转化为\(B_{l-1}\)+=\(a_0\),\(B ...

  5. S-T平面图中利用最短路求最小割(BZOJ 1001)

    BZOJ 1001: [BeiJing2006]狼抓兔子 最小割 题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1001 现在小朋友们最喜欢 ...

  6. BZOJ 1124: [POI2008]枪战Maf(构造 + 贪心)

    题意 有 \(n\) 个人,每个人手里有一把手枪.一开始所有人都选定一个人瞄准(有可能瞄准自己).然后他们按某个顺序开枪,且任意时刻只有一个人开枪. 因此,对于不同的开枪顺序,最后死的人也不同. 问最 ...

  7. BZOJ 2957楼房重建

    传送门 线段树 //Twenty #include<cstdio> #include<cstdlib> #include<iostream> #include< ...

  8. BZOJ.5249.[九省联考2018]iiidx(贪心 线段树)

    BZOJ LOJ 洛谷 \(d_i\)不同就不用说了,建出树来\(DFS\)一遍. 对于\(d_i\)不同的情况: Solution 1: xxy tql! 考虑如何把这些数依次填到树里. 首先对于已 ...

  9. bzoj 4871: [Shoi2017]摧毁“树状图”

    4871: [Shoi2017]摧毁"树状图" Time Limit: 25 Sec  Memory Limit: 512 MB Submit: 53  Solved: 9 [Su ...

最新文章

  1. ASPX页面中不放置Form元素的问题
  2. mysql wampmysqld_wamp中mysqld占用内存大mysql5.6 | 学步园
  3. java读取文件路径中文,分分钟搞定!
  4. Talairach空间、MNI空间、Native空间、Stereotaxic空间
  5. matlab矩阵分解
  6. VirtualAlloc和VirtualCopy----VirtualFree
  7. 【渝粤教育】电大中专建设工程法规1作业 题库
  8. python选定区域设置边框_Python教程:巧用openpyxl为指定区域设置边框为粗匣框线...
  9. count和distinct如何一起使用_轻松玩转乐高积木:教你如何使用颗粒分离器
  10. ibm邮件怎么撤回_怎么申请邮箱?163邮箱如何注册使用?
  11. 遥感数据集_最新高光谱遥感数据集
  12. Ceres Solver (ubuntu 安装)
  13. 软考报名时间 流程 条件
  14. Windows 10做了这9项优化 电脑跑得比谁都快
  15. 6.在SAP Web上实现Punchout目录采购(第一部分)
  16. csp-j2022比赛心得
  17. 电力电子技术的matlab实践 下载,电力电子技术MATLAB仿真实践指导及应用
  18. vmybatis #{} 以及 ${}与sql注入
  19. win7虚拟机上安装visual studio2017社区版的相关问题以及解决办法
  20. Google中国博客开通啦~!!

热门文章

  1. android 指定资源id,Android 通过名称获取资源ID
  2. vscode extension
  3. flask request传参
  4. python I/O原理
  5. 2.2 清除标注错误的数据
  6. 数据算法之二叉树平衡(BinTreeNode Rotate)的Java实现
  7. openlayers属性数据mysql_OpenLayers学习笔记8——使用servlet从mysql获取数据并标注
  8. mysql sql sysdate_MySQL与Oracle SQL语言差异比较一览
  9. android智能手机发展,2011 LG Android智能手机发展蓝图
  10. java 3d模型插件_3D模型整合插件 Kitbasher V1.2 支持3DS MAX 2012~2018