题意:统计一段字符串中形如UVU的子串个数(其中V的长度固定为g)。

问题等价于求满足$g+1\leqslant |j-i|\leqslant g+LCP(i,j)$的后缀(i,j)的对数,即$\sum\limits_{i<j}[g+1\leqslant |j-i|\leqslant g+LCP(i,j)]$。

由于将原串反转后的后缀(i,j)的LCP等于其在原串的后缀自动机上对应结点的LCA的最大长度,可以枚举LCA,在fail树上将right数组启发式合并即可。

 #include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+,M=;
char s[N];
int n,fa[N],go[N][M],mxl[N],last,tot,g,ss[N],c[N],ka;
int rt[N],ls[N*],rs[N*],sum[N*],tot2,ans[N];
#define mid ((l+r)>>1)
int newnode2() {int u=++tot2; sum[u]=ls[u]=rs[u]=; return u;}
void upd(int& u,int p,int l=,int r=n-) {
if(!u)u=newnode2();
sum[u]++;
if(l==r)return;
p<=mid?upd(ls[u],p,l,mid):upd(rs[u],p,mid+,r);
}
void mg(int& u,int v) {
if(!u||!v) {u=u|v; return;}
sum[u]+=sum[v];
mg(ls[u],ls[v]),mg(rs[u],rs[v]);
}
int qry(int u,int L,int R,int l=,int r=n-) {
if(l>=L&&r<=R)return sum[u];
if(l>R||r<L)return ;
return qry(ls[u],L,R,l,mid)+qry(rs[u],L,R,mid+,r);
}
void dfs(int u,int v,int l=,int r=n-) {
if(!sum[v])return;
if(l==r) {
ans[u]+=qry(rt[u],l+(+g),l+(mxl[u]+g));
ans[u]+=qry(rt[u],l-(mxl[u]+g),l-(+g));
return;
}
dfs(u,ls[v],l,mid),dfs(u,rs[v],mid+,r);
}
int newnode(int l) {int u=++tot; rt[u]=ans[u]=,mxl[u]=l,memset(go[u],,sizeof go[u]); return u;}
void add(int ch,int r) {
int p=last,np=last=newnode(mxl[p]+);
upd(rt[np],r);
for(; p&&!go[p][ch]; p=fa[p])go[p][ch]=np;
if(!p)fa[np]=;
else {
int q=go[p][ch];
if(mxl[q]==mxl[p]+)fa[np]=q;
else {
int nq=newnode(mxl[p]+);
memcpy(go[nq],go[q],sizeof go[q]);
fa[nq]=fa[q],fa[q]=fa[np]=nq;
for(; p&&go[p][ch]==q; p=fa[p])go[p][ch]=nq;
}
}
}
void solve() {
for(int i=; i<=tot; ++i)c[i]=;
for(int i=; i<=tot; ++i)++c[mxl[i]];
for(int i=; i<=tot; ++i)c[i]+=c[i-];
for(int i=; i<=tot; ++i)ss[--c[mxl[i]]]=i;
for(int i=tot-; i>=; --i) {
int v=ss[i],u=fa[v];
if(!u)continue;
if(sum[rt[v]]>sum[rt[u]])swap(rt[u],rt[v]);
dfs(u,rt[v]),mg(rt[u],rt[v]);
ans[u]+=ans[v];
}
}
int main() {
int T;
for(scanf("%d",&T); T--;) {
scanf("%d%s",&g,s),n=strlen(s);
tot=tot2=,last=newnode();
for(int i=; i<n; ++i)add(s[i]-'a',i);
solve();
printf("Case %d: %d\n",++ka,ans[]);
}
return ;
}

UVA - 10829 L-Gap Substrings (后缀自动机+线段树启发式合并)的更多相关文章

  1. Bzoj2534:后缀自动机 主席树启发式合并

    国际惯例的题面:考虑我们求解出字符串uvu第一个u的右端点为i,第二个u的右端点为j,我们需要满足什么性质?显然j>i+L,因为我们选择的串不能是空串.另外考虑i和j的最长公共前缀(也就是说其p ...

  2. BZOJ3413: 匹配(后缀自动机 线段树合并)

    题意 题目链接 Sol 神仙题Orz 后缀自动机 + 线段树合并... 首先可以转化一下模型(想不到qwq):问题可以转化为统计\(B\)中每个前缀在\(A\)中出现的次数.(画一画就出来了) 然后直 ...

  3. cf666E. Forensic Examination(广义后缀自动机 线段树合并)

    题意 题目链接 Sol 神仙题Orz 后缀自动机 + 线段树合并 首先对所有的\(t_i\)建个广义后缀自动机,这样可以得到所有子串信息. 考虑把询问离线,然后把\(S\)拿到自动机上跑,同时维护一下 ...

  4. 洛谷P2178 [NOI2015]品酒大会(后缀自动机 线段树)

    题意 题目链接 Sol 说一个后缀自动机+线段树的无脑做法 首先建出SAM,然后对parent树进行dp,维护最大次大值,最小次小值 显然一个串能更新答案的区间是\([len_{fa_{x}} + 1 ...

  5. BZOJ1396: 识别子串(后缀自动机 线段树)

    题意 题目链接 Sol 后缀自动机+线段树 还是考虑通过每个前缀的后缀更新答案,首先出现次数只有一次,说明只有\(right\)集合大小为\(1\)的状态能对答案产生影响 设其结束位置为\(t\),代 ...

  6. [Luogu5161]WD与数列(后缀数组/后缀自动机+线段树合并)

    https://blog.csdn.net/WAautomaton/article/details/85057257 解法一:后缀数组 显然将原数组差分后答案就是所有不相交不相邻重复子串个数+n*(n ...

  7. 洛谷P4493 [HAOI2018]字串覆盖(后缀自动机+线段树+倍增)

    题面 传送门 题解 字符串就硬是要和数据结构结合在一起么--\(loj\)上\(rk1\)好像码了\(10k\)的样子-- 我们设\(L=r-l+1\) 首先可以发现对于\(T\)串一定是从左到右,能 ...

  8. 模板—字符串—后缀自动机(后缀自动机+线段树合并求right集合)

    模板—字符串—后缀自动机(后缀自动机+线段树合并求right集合) Code: #include <bits/stdc++.h> using namespace std; #define ...

  9. 【BZOJ4556】[TJOI2016&HEOI2016] 字符串(后缀自动机+线段树合并+二分)

    点此看题面 大致题意: 给你一个字符串\(s\),每次问你一个子串\(s[a..b]\)的所有子串和\(s[c..d]\)的最长公共前缀. 二分 首先我们可以发现一个简单性质,即要求最长公共前缀,则我 ...

随机推荐

  1. KVM虚拟化网络管理(4)

    一.Linux Bridge网桥管理 网络虚拟化是虚拟化技术中最复杂的部分,也是非常重要的资源.第一节中我们创建了一个名为br0的linux-bridge网桥,如果在此网桥上新建一台vm,如下图: V ...

  2. 使用PowerShell 自动安装.NET4.6.1离线包

    自动安装脚本在文章末尾 自动安装脚本在文章末尾 自动安装脚本在文章末尾 运行环境:Windows Server 2012 R2 开发环境:Win10 Microsoft .NET Framework ...

  3. netcore发布的坑

    当我选择目标运行时为Linux-64时,生成的接口为第二图, 而当我选择目标运行时为可移植或windows-64时,生成的接口则是正确的.和我写的代码,以及本地按F5启动调试的效果一致. 整个项目从v ...

  4. [转帖]微软 SQL Server 2008/R2 停止支持

    微软 SQL Server 2008/R2 停止支持 微软停止支持 SQLSERVER 2008R2 https://t.cj.sina.com.cn/articles/view/3172142827 ...

  5. Java switch case 语句

    switch case 语句判断一个变量与一系列值中某个值是否相等,每个值称为一个分支. 语法 switch(expression){ case value : //语句 break; //可选 ca ...

  6. js、jQuery各种高度

    height.js ```$(document).height(); //整个网页的高度 $(window).height(); //浏览器可视窗口的高度 $(window).scrollTop(); ...

  7. Codeforces 1178B. WOW Factor

    传送门 显然对每个 $o$ ,考虑左边和右边分别有多少 $w$,那么这个 $o$ 的贡献就是左右 $w$ 的出现次数相乘 $w$ 的出现次数可以直接根据每一段连续的 $v$ 得到 那么从左到右扫一遍, ...

  8. python网络爬虫(7)爬取静态数据详解

    目的 爬取http://seputu.com/数据并存储csv文件 导入库 lxml用于解析解析网页HTML等源码,提取数据.一些参考:https://www.cnblogs.com/zhangxin ...

  9. CentOS 7系统安装Jenkins

    一.jenkins 介绍 Jenkins是一个开源的.可扩展的持续集成.交付.部署(软件/代码> 的编译.打包.部署)基于web界面的平台. 简单说,就是各种项目的"自动化" ...

  10. macOS Sierra 如何安装任何来源的软件

    为了安全性考虑,macos是要手动勾选来自任何来源的选项才可以安装第三方应用软件,系统升级后,在新的系统中这一项是默认不显示的,如果想要出现和这一勾选选项,可以从终端中输入 sudo spctl -- ...