CF1276F-Asterisk Substrings【SAM,线段树合并】

正题

题目链接:https://www.luogu.com.cn/problem/CF1276F


题目大意

给出一个长度为nnn的字符串SSS,现在依次进行如下操作

  1. 取出SSS的一个子串TTT
  2. TTT中的一个字符替换成∗*号(也可以不替换)

求最后有多少种不同的TTT


解题思路

发现最终其实只有4种情况,T,T∗,∗T,T1∗T2T,T*,*T,T_1*T_2T,T,T,T1T2

前面三种很好记录,主要考虑最后一种。

对于T1T_1T1来说,同一个endposendposendpos等价类中的子串对应的T2T_2T2数量应该也是相同的。

那我们肯定是先建一个SAMSAMSAM这样就可以知道每个endposendposendpos等价类了。

那么考虑怎么统计T2T_2T2的数量,其实对应iii在某个endposendposendpos里,那么我们就只需要考虑从i+2i+2i+2这些位置开始的不同串的数量。

也就是确定起始位置的子串,这提醒我们反着再建立一个SAMSAMSAM,然后把所有i+2i+2i+2位置的点标记了,这些点和根在failfailfail树上的虚树路径长度和就是我们要知道的答案。

那么怎么维护这个东西呢,我们在正着的SAMSAMSAM上每个点维护一个线段树,然后统计反着的SAMSAMSAM上的链并长度,这个显然是可以用线段树合并的。

时间复杂度:O(nlog⁡2n)O(n\log^2 n)O(nlog2n)(如果肯写O(1)O(1)O(1)LCA的话可以做到O(nlog⁡n)O(n\log n)O(nlogn)


code

#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const ll N=2e5+10,M=N<<5;
struct SAM{ll cnt,last,len[N],pos[N],fa[N],ch[N][26];void Ins(ll c,ll id){ll p=last,np=last=++cnt;len[np]=len[p]+1;pos[id]=np;for(;p&&!ch[p][c];p=fa[p])ch[p][c]=np;if(!p)fa[np]=1;else{ll q=ch[p][c];if(len[p]+1==len[q])fa[np]=q;else{ll nq=++cnt;len[nq]=len[p]+1;memcpy(ch[nq],ch[q],sizeof(ch[nq]));fa[nq]=fa[q];fa[q]=fa[np]=nq;for(;p&&ch[p][c]==q;p=fa[p])ch[p][c]=nq;}}return;}
}Suf,Pre;
struct node{ll to,next;
}a[N];
ll n,m,tot,cnt,ls[N],siz[N],dep[N],rt[N];
ll dfn[N],rfn[N],son[N],top[N],ans=2;
char s[N];
void addl(ll x,ll y){a[++tot].to=y;a[tot].next=ls[x];ls[x]=tot;return;
}
void dfs1(ll x){siz[x]=1;for(ll i=ls[x];i;i=a[i].next){ll y=a[i].to;dep[y]=dep[x]+1;dfs1(y);siz[x]+=siz[y];if(siz[y]>siz[son[x]])son[x]=y;}return;
}
void dfs2(ll x){dfn[++cnt]=x;rfn[x]=cnt;if(son[x]){top[son[x]]=top[x];dfs2(son[x]);}for(ll i=ls[x];i;i=a[i].next){ll y=a[i].to;if(y==son[x])continue;top[y]=y;dfs2(y);}return;
}
ll LCA(ll x,ll y){while(top[x]!=top[y]){if(dep[top[x]]<dep[top[y]])swap(x,y);x=Suf.fa[top[x]];}return (dep[x]<dep[y])?x:y;
}
struct SegTree{ll cnt,ls[M],rs[M],w[M],pl[M],pr[M];void Merge(ll x){if(!ls[x]||!rs[x]){ll p=ls[x]|rs[x];w[x]=w[p];pl[x]=pl[p];pr[x]=pr[p];}else{w[x]=w[ls[x]]+w[rs[x]]-Suf.len[LCA(pr[ls[x]],pl[rs[x]])];pl[x]=pl[ls[x]];pr[x]=pr[rs[x]];}return;}void Change(ll &x,ll L,ll R,ll pos){if(!x)x=++cnt;if(L==R){w[x]=Suf.len[dfn[L]];pl[x]=pr[x]=dfn[L];return;}ll mid=(L+R)>>1;if(pos<=mid)Change(ls[x],L,mid,pos);else Change(rs[x],mid+1,R,pos);Merge(x);return;}ll Merge(ll x,ll y,ll L,ll R){if(!x||!y)return x|y;ll mid=(L+R)>>1;ls[x]=Merge(ls[x],ls[y],L,mid);rs[x]=Merge(rs[x],rs[y],mid+1,R);Merge(x);return x;}
}T;
void solve(ll x){for(ll i=ls[x];i;i=a[i].next){ll y=a[i].to;solve(y);rt[x]=T.Merge(rt[x],rt[y],1,cnt);}ans+=T.w[rt[x]]*(Pre.len[x]-Pre.len[Pre.fa[x]]);return;
}
signed main()
{scanf("%s",s+1);n=strlen(s+1);Pre.last=Pre.cnt=Suf.last=Suf.cnt=1;for(ll i=n;i>1;i--)Suf.Ins(s[i]-'a',i);for(ll i=1;i<n;i++)Pre.Ins(s[i]-'a',i);for(ll i=1;i<=Pre.cnt;i++)ans+=Pre.len[i]-Pre.len[Pre.fa[i]];for(ll i=1;i<=Suf.cnt;i++)ans+=Suf.len[i]-Suf.len[Suf.fa[i]];Suf.Ins(s[1]-'a',1);Pre.Ins(s[n]-'a',n);for(ll i=2;i<=Suf.cnt;i++)addl(Suf.fa[i],i),ans+=Suf.len[i]-Suf.len[Suf.fa[i]];dfs1(1);top[1]=1;dfs2(1);tot=0;memset(ls,0,sizeof(ls));for(ll i=2;i<=Pre.cnt;i++)addl(Pre.fa[i],i);for(ll i=1;i<n-1;i++)T.Change(rt[Pre.pos[i]],1,cnt,rfn[Suf.pos[i+2]]);solve(1);printf("%lld\n",ans);return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/317352.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

线性代数三之状压DP的矩阵加速——Quad Tiling,Bus公交线路

状压与矩阵加速的藕断丝连Quad Tilingdescriptionsolutioncode[Hnoi2010]Bus 公交线路descriptionsolutioncodeQuad Tiling description solution 设dpi,S:dp_{i,S}:dpi,S​: iii列的状态为SSS的方案数&#xff0c;最后答案为dpn,(1<<4)−1dp_{n,(1<<4)-1}dpn,(…

codeforces:812(div2):总结

前言 比较水的一场比赛 E题几乎是一本通原题而我还是不会做qwq A - Sagheer and Crossroads 有一个十字路口&#xff0c;给出四个路口的车是否可以左转/右转/直行&#xff0c;并且给出每个路口的行人是否可以通过&#xff0c;求是否出现车和人冲突的情况 阅读理解题&#xff…

如何在ASP.NET Core程序启动时运行异步任务(2)

原文&#xff1a;Running async tasks on app startup in ASP.NET Core (Part 2)作者&#xff1a;Andrew Lock译者&#xff1a;Lamond Lu在我的上一篇博客中&#xff0c;我介绍了如何在ASP.NET Core应用程序启动时运行一些一次性异步任务。本篇博客将继续讨论上一篇的内容&…

Gym 102798A Golden Spirit

VJ链接 题意&#xff1a; 河的两岸各有n个人&#xff0c;中间有个桥&#xff0c;过桥时间为t&#xff0c;所有人过桥后要休息x时间&#xff0c;你每次可以带一个人过桥&#xff08;每次最多只能带一个人&#xff09;&#xff0c;问将所有人带到对岸并带回来&#xff0c;最短需…

P8347-「Wdoi-6」另一侧的月【博弈论,结论】

正题 题目链接:https://www.luogu.com.cn/problem/P8347 题目大意 给出一棵树&#xff0c;两个人轮流操作。 操作者可以选择一个点删除&#xff0c;然后选择一个剩下的连通块&#xff0c;删除其他连通块。 操作完成后只剩下一个点的人失败&#xff0c;求是否先手必败。 1≤…

线性代数四之动态DP(广义矩阵加速)——Can you answer these queries III,保卫王国

动态DP——广义矩阵加速SP1716 GSS3 - Can you answer these queries IIIdescriptionsolutioncode[NOIP2018 提高组] 保卫王国descriptionsolutioncode动态DP能矩阵加速要满足外层操作符对内层操作符具有分配率加法对于乘法就具有分配率(ab)*ca*cb*c SP1716 GSS3 - Can you a…

洛谷P4219 大融合(LCT、虚子树)

解析 本题需要用LCT维护子树大小 然后我就不会了 然后我就用树剖水过去了 又快又好写&#xff0c;真香 现在详细聊聊如何用LCT维护子树信息 每个结点再定义一个新的变量记录所有虚儿子的信息 然后…完了&#xff1f; 告别盲目pushup&#xff0c;我们来详细聊聊在哪里需要更新…

.Net Core跨平台应用研究-HelloArm(串口篇)

引言为了验证采用dotnet core技术开发的物联网设备数据采集接入服务应用是否能在高性价比的linux嵌入式平台运行&#xff0c;针对dotnet core应用程序进行嵌入式linux环境的发布部署运行验证研究。硬件环境硬件系统经过对比筛选&#xff0c;选用了友善之臂出品的NanoPC-T3 Plus…

H - Message Bomb Gym - 102798H

H - Message Bomb Gym - 102798H 题意&#xff1a; 有n个团队&#xff0c;m个人&#xff0c;s个操作 操作1&#xff1a;学生x加入y团队 操作2&#xff1a;学生x推出y团队 操作3&#xff1a;学生x在团队y发送一个信号&#xff0c;在团队y内的所有成员&#xff08;除了x&#x…

Loj#3005-「JOISC 2015 Day 4」Limited Memory【交互题】

正题 题目链接:https://loj.ac/p/3005 题目大意 有一个长度为nnn的括号串SSS&#xff0c;其中包括[]和<>两种括号类型&#xff0c;一个合法的括号串要求同类型的括号一一对应。 你每次可以询问SSS中的一个字符并且传递一个[0,222)[0,2^{22})[0,222)的数字到下一次。 …

[数论系列一]C Looooops,跳跳棋,The Luckiest number,CF906D Power Tower,Minimal Power of Prime,仪仗队,LCMSUM

文章目录C Looooopsdescriptionsolutioncode跳跳棋descriptionsolutioncodeThe Luckiest numberdescriptionsolutioncodeCF906D Power TowerdescriptionsolutioncodeMinimal Power of Primedescriptionsolutioncode[SDOI2008]仪仗队descriptionsolutioncodeLCMSUMdescriptionso…

P4299 首都(LCT、重心)

解析 动态维护树的重心 关键性质&#xff1a;两棵树合并时&#xff0c;新的重心一定在两个原重心之间的路径上 把两个重心之间的路径提出来&#xff0c;利用splay本身的二叉结构二分即可 注意虚子树信息的处理 不要忘记pushdown 代码 #include<bits/stdc.h> using nam…

.NET Core使用微软AI认知服务识别文字语言

点击上方蓝字关注“汪宇杰博客”识别一段文字的语言有多种途径&#xff0c;在这个以AI为热点的时代&#xff0c;我们也可以给自己的应用强行加上AI&#xff0c;然后就能加上“智慧”的名字“自主研发成功”后去吹牛逼。今天我带大家来看看如何使用微软智慧云Azure提供的AI认知服…

2020CCPC威海

2020CCPC威海 2020CCPC威海榜单 题号题目知识点难度AGolden Spirit思维&#xff0c;推导题签到题BLabyrinthdfs思维金牌题CRencontreDABC Conjecture数论&#xff0c;推导签到题ESo Many Possibilities…FSkeleton DynamizationGCaesar Cipher线段树hash银牌题HMessage Bomb贪…

P6118-[JOI 2019 Final]珍しい都市【树的直径】

正题 题目链接:https://www.luogu.com.cn/problem/P6118 题目大意 给出一棵nnn个点的树&#xff0c;对于一个点xxx来说&#xff0c;独特的点y(y≠x)y(y\neq x)y(y​x)是指不存在zzz使得dis(y,x)dis(z,x)dis(y,x)dis(z,x)dis(y,x)dis(z,x)&#xff0c;其中x≠z,y≠zx\neq z,…

[NOI2021 day1]轻重边(树链剖分),路径交点(矩阵行列式)

NOI 2021 day1轻重边descriptionsolutioncode路径交点descriptionsolutioncode轻重边 description solution case1~6 把父亲和儿子的边转化为储存在儿子上的点 建树&#xff0c;暴力爬lcalcalca&#xff0c;暴力修改&#xff0c;O(n2)O(n^2)O(n2) caseA 对于一条链的情况&am…

模板:CDQ分治

文章目录前言upd例题P3810 【模板】三维偏序&#xff08;陌上花开&#xff09;P2487 [SDOI2011]拦截导弹所谓CDQ分治&#xff0c;就是和由Conprour、Doctorjellyfish、QE添一同发明的分治算法 &#xff08;逃&#xff09; 前言 神奇的乱搞黑科技 CDQ分治能够通过更小的时间常…

【NET CORE微服务一条龙应用】第二章 配置中心使用

背景系列目录&#xff1a;【NET CORE微服务一条龙应用】开始篇与目录在分布式或者微服务系统里&#xff0c;通过配置文件来管理配置内容&#xff0c;是一件比较令人痛苦的事情&#xff0c;再谨慎也有湿鞋的时候&#xff0c;这就是在项目架构发展的过程中&#xff0c;配置中心存…

D - ABC Conjecture Gym - 102798D

D - ABC Conjecture Gym - 102798D 题意&#xff1a; 规定rad(n)n的所有质因子的乘积 给你一个c&#xff0c;问能否构造a和b使得abc且rad(abc)<c 题解&#xff1a; 先说结论&#xff0c;如果c可以拆分出两个一样的质因子&#xff0c;则能构造a和b 即 np1a1 * p2a2 . . .…

P7560-[JOISC 2021 Day1]フードコート【吉司机线段树】

正题 题目链接:https://www.luogu.com.cn/problem/P7560 题目大意 有nnn个队列&#xff0c;要求支持操作&#xff1a; 往[L,R][L,R][L,R]的队列中插入kkk个ccc。出队[L,R][L,R][L,R]中的kkk个元素。&#xff08;如果不足kkk个就全部出队&#xff09;求第aaa个队列中的第bbb个…