2019牛客暑期多校训练营(第六场)C:Palindrome Mouse(回文树+树剖)
题意:给定字符串Str,求出回文串集合为S,问S中的(a,b)满足a是b的子串的对数。
思路:开始和题解的思路差不多,维护当前后缀的每个串的最后出现位置,但是不知道怎么套“最小回文分割”,所以想到了树剖,但是树剖不好同时维护“最后出现的次数”,“查询左端点>=L”的位置数。 所以GG。 那么从图论的角度考虑,有向图,问多少个点可以到达的关系点对,(我怎么只会bitset解决小数据问题)。
1,而回文树的特殊性在于,每个点只有一个fail(回边),25个next(出边),那么把回边抽离出来建立fail树。那么就是顺着next可以得到答案,问题是要去重。
去重的过程可以加一个vis数组标记即可。 这种有向图,DFS可做。
2,这里为了和比赛的时候想法接近一下,是用树剖实现的。 fail树上树剖,next指针搜索,每次把当前点的fail链标记量++; 回溯的时候标记量--;由于都是先加后删,所以没必要下推tag,这样反而保证了复杂度。
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=;
int tot; struct PAT
{
struct node{
int len,num,fail,son[];
}t[maxn];
int last,n,s[maxn];
void init()
{
memset(t,,sizeof(t));
tot=last=; n=;
t[].len=; t[].len=-;
t[].fail=t[].fail=;
s[]=-;
}
int add(int c){
int p=last; s[++n]=c;
while(s[n]!=s[n--t[p].len]) p=t[p].fail;
if(!t[p].son[c]){
int v=++tot,k=t[p].fail;
while(s[n]!=s[n-t[k].len-]) k=t[k].fail;
t[v].fail=t[k].son[c];
t[v].len=t[p].len+;
t[v].num=t[t[v].fail].num+;
t[p].son[c]=v;
}
last=t[p].son[c];
return t[last].num;
}
}T;
char c[maxn];
int Laxt[maxn],Next[maxn],To[maxn],cnt;
int son[maxn],Top[maxn],fa[maxn],pos[maxn],times;
int tag[maxn<<],sum[maxn<<],sz[maxn];
void Add(int u,int v)
{
Next[++cnt]=Laxt[u]; Laxt[u]=cnt; To[cnt]=v;
}
void dfs1(int u,int f)
{
sz[u]=; son[u]=; fa[u]=f;
for(int i=Laxt[u];i;i=Next[i]){
if(To[i]!=f){
dfs1(To[i],u);
sz[u]+=sz[To[i]];
if(sz[To[i]]>sz[son[u]]) son[u]=To[i];
}
}
}
void dfs2(int u,int tp)
{
Top[u]=tp; pos[u]=++times;
if(son[u]) dfs2(son[u],tp);
for(int i=Laxt[u];i;i=Next[i]){
if(To[i]==son[u]) continue;
dfs2(To[i],To[i]);
}
}
void pushup(int Now,int L,int R)
{
if(tag[Now]) sum[Now]=R-L+;
else if(L==R) sum[Now]=;
else sum[Now]=sum[Now<<]+sum[Now<<|];
}
void add(int Now,int L,int R,int l,int r,int x)
{
if(l<=L&&r>=R) {
tag[Now]+=x;
pushup(Now,L,R);
return ;
}
int Mid=(L+R)>>;
if(l<=Mid) add(Now<<,L,Mid,l,r,x);
if(r>Mid) add(Now<<|,Mid+,R,l,r,x);
pushup(Now,L,R);
}
int query(int Now,int L,int R,int l,int r)
{
if(l<=L&&r>=R){
if(tag[Now]) return R-L+;
if(L==R) return ;
return sum[Now<<]+sum[Now<<|];
}
int res=,Mid=(L+R)>>;
if(l<=Mid) res+=query(Now<<,L,Mid,l,r);
if(r>Mid) res+=query(Now<<|,Mid+,R,l,r);
pushup(Now,L,R);
return res;
}
void ADD(int p,int x)
{
while(Top[p]!=) {
add(,,tot,pos[Top[p]],pos[p],x);
p=T.t[Top[p]].fail;
}
if(p!=) add(,,tot,,pos[p],x);
}
long long ans;
void solve(int u)
{
if(u>) ADD(u,),ans+=sum[]-;
rep(i,,)
if(T.t[u].son[i])
solve(T.t[u].son[i]);
if(u>) ADD(u,-);
}
int main()
{
int TT,C=,N;
scanf("%d",&TT);
while(TT--){
T.init(); ans=; times=;
scanf("%s",c+); N=strlen(c+);
rep(i,,N) T.add(c[i]-'a');
rep(i,,tot) Laxt[i]=; cnt=;
rep(i,,tot) {
if(T.t[i].fail==) T.t[i].fail=;
Add(T.t[i].fail,i);
}
dfs1(,); dfs2(,);
solve();
solve();
printf("Case #%d: %lld\n",++C,ans);
}
return ;
}
2019牛客暑期多校训练营(第六场)C:Palindrome Mouse(回文树+树剖)的更多相关文章
- 2019牛客暑期多校训练营(第六场)C - Palindrome Mouse (回文自动机)
https://ac.nowcoder.com/acm/contest/886/C 题意: 给出一个串A , 集合S里面为A串的回文字串 , 现在在集合S里面找出多少对(a,b),b为a的字串 分析: ...
- 2019牛客暑期多校训练营(第九场)H Cutting Bamboos(主席树+二分)
题意:n个竹子,有高度,q次询问,询问之间是独立的,每次查询输入l,r,x,y代表砍区间[l,r]]内的竹子砍y次,最后一次要砍成0,每次砍掉的总长度相同,问第x次砍的高度是多少. 既然每次要求砍掉的 ...
- 2019牛客暑期多校训练营(第一场)I Points Division(dp+线段树优化)
给你n个点,第i个点在的位置为(xi,yi),有两个属性值(ai,bi).现在让你把这n个点划分为A和B两个部分,使得最后不存在i∈A和j∈B,使得xi>=xj且yi<=yj.然后对于所有 ...
- 2019牛客暑期多校训练营(第六场)J Upgrading Technology
传送门 题意: 就是给你n个技能,每个技能最高升到m级,每升一级就是耗费Cij钱,这个Cij可能是负的,如果所有技能都升到或者说超过j等级,就会获得Dj钱,这个Dj也有可能是负值,让你求你最多得到多少 ...
- 2019牛客暑期多校训练营(第九场)A:Power of Fibonacci(斐波拉契幂次和)
题意:求Σfi^m%p. zoj上p是1e9+7,牛客是1e9: 对于这两个,分别有不同的做法. 前者利用公式,公式里面有sqrt(5),我们只需要二次剩余求即可. 后者mod=1e9,5才 ...
- 2019牛客暑期多校训练营(第一场)A题【单调栈】(补题)
链接:https://ac.nowcoder.com/acm/contest/881/A来源:牛客网 题目描述 Two arrays u and v each with m distinct elem ...
- 2019牛客暑期多校训练营(第一场) B Integration (数学)
链接:https://ac.nowcoder.com/acm/contest/881/B 来源:牛客网 Integration 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 5242 ...
- 2019牛客暑期多校训练营(第一场) A Equivalent Prefixes ( st 表 + 二分+分治)
链接:https://ac.nowcoder.com/acm/contest/881/A 来源:牛客网 Equivalent Prefixes 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/ ...
- 2019牛客暑期多校训练营(第二场)F.Partition problem
链接:https://ac.nowcoder.com/acm/contest/882/F来源:牛客网 Given 2N people, you need to assign each of them ...
- 2019牛客暑期多校训练营(第一场)A Equivalent Prefixes(单调栈/二分+分治)
链接:https://ac.nowcoder.com/acm/contest/881/A来源:牛客网 Two arrays u and v each with m distinct elements ...
随机推荐
- javascript 忍者秘籍读书笔记
书名 "学徒"=>"忍者" 性能分析 console.time('sss') console.timeEnd('sss') 函数 函数是第一类对象 通过字 ...
- [转帖]k8s 基本使用(上)
k8s 基本使用(上) https://www.jianshu.com/p/8d60ce1587e1 本文将介绍 k8s 中的一些最基本的命令,并辅以解释一些基本概念来方便理解,也就是说,本文是一篇偏 ...
- 公众号后台开发(SpingMVC接收与响应公众号消息)
1.准备 1.准备服务 与微信对接的url要具备以下条件: (1)在公网上能够访问 (2)端口只支持80端口 在这里如果是公网能够访问的服务最好,也可以通过花生壳或者其他外网映射工具进行映射,比如ng ...
- Java 在 Word 文档中使用新文本替换指定文本
创作一份文案,经常会高频率地使用某些词汇,如地名.人名.人物职位等,若表述有误,就需要整体撤换.文本将介绍如何使用Spire.Doc for Java,在Java程序中对Word文档中的指定文本进行替 ...
- SQL系列(十四)—— 视图(view)
说到视图view,大家应该都很熟悉.如几何学中用三视图来描述集合物体的外观构成,三视图中反应出物体的面貌.这里我们讨论数据库中视图的概念: 什么是视图 为什么会有会用视图 怎样使用视图 视图与表的异同 ...
- reactiveX沉思(草稿)
一.第一性原理 将异步的io.事件解释为observable.并借用observer的一些类概念进行处理. ReactiveX is a library for composing asynchron ...
- 尝试 WebAssembly
wasm 为浏览器应用开辟了一个全新的领域.意义非凡,并不是一句两句说的清的,今天正好有点空做些实验. 1. emsdk 的安装 Emscripten 可以直接将 C/C++ 编译为 wasm,让用 ...
- 人脸跟踪开源项目HyperFT代码算法解析及改进
一.简介 人脸识别已经成为计算机视觉领域中最热门的应用之一,其中,人脸信息处理的第一个环节便是人脸检测和人脸跟踪.人脸检测是指在输入的图像中确定所有人脸的位置.大小和姿势的过程.人脸跟踪是指在图像序列 ...
- Java自学-数字与字符串 操纵字符串
Java常见字符串方法 示例 1 : 获取字符 charAt(int index)获取指定位置的字符 package character; public class TestString { publ ...
- MTSC2019-深圳站 议题征集
议题截止时间 11月初 议题投递地址 topic@testerhome.com 臣一路走来,没有敌人,看见的都是朋友和师长 —司马懿 关于中国移动互联网测试大会 MTSC 大会(中国移动互联网测试 ...