题目传送门

题意:给出一个字符串,将字符串中所有的回文子串全部放入一个集合里,去重后。问这个集合里有几对<a,b>,使得a是b的子串。

思路:一开始想偏了,以为只要求每个回文串的回文后缀的数量加去掉开头结尾字符的数量就可以了。事实上,如果我们把去掉两个字符的字符串称为父节点,那么父节点的回文后缀和自己也能形成这样的pair。

  设一个字符串x能产生的贡献为$dp[x]$,我们考虑x能产生的贡献是什么呢?

  一个是和自己本身的所有回文后缀结合产生的贡献,这一个可以通过回文树上跳fail来完成。

  一个是和自己的父节点结合,这个价值只有1,且要求父节点不是0或者1,当然自己也不能是0或者1.

  还有一个是父节点能产生的贡献,这个就考虑到了父节点父节点和自己还有父节点的回文后缀和自己,此处可以通过dfs来得到。

  一个子串可能同时是自己的祖先节点和回文后缀,这种情况要标记一下,不能重复计算,比如$aaa$。如果不停的掉fail,那么会跳到最后一个字符$a$,但$a$同时也是自己的父节点。

#pragma GCC optimize (2)
#pragma G++ optimize (2)
#pragma comment(linker, "/STACK:102400000,102400000")
#include<bits/stdc++.h>
#include<cstdio>
#include<vector>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define dep(i,b,a) for(int i=b;i>=a;i--)
#define clr(a,b) memset(a,b,sizeof(a))
#define pb push_back
#define pii pair<int,int >
using namespace std;
typedef long long ll;
ll rd()
{
ll x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
const int maxn=;
char s[maxn];
ll dp[maxn];
int vis[maxn],cat=;
struct Palindromic_Tree
{
struct Node
{
int son[];
int ff,len;
}t[maxn];
int last,tot;
ll ans=;
void init()
{
memset(t,,sizeof(t[])*(tot+));
tot=last=ans=;
t[++tot].len=-;
t[].ff=t[].ff=;
}
void extend(int c,int n)
{
int p=last;
while(s[n-t[p].len-]!=s[n])p=t[p].ff;
if(!t[p].son[c])
{
int v=++tot,k=t[p].ff;
t[v].len=t[p].len+;
while(s[n-t[k].len-]!=s[n])k=t[k].ff;
t[v].ff=t[k].son[c];
t[p].son[c]=v;
}
last=t[p].son[c];
}
void dfs(int x,int fa){
ll cnt=;
int cx=t[x].ff;
vis[x]++;
while(cx!=&&cx!=&&vis[cx]==){vis[cx]++;cnt++;cx=t[cx].ff;
}
dp[x]=cnt;
if(x!=&&x!=&&fa!=&&fa!=)dp[x]=dp[fa]+cnt+;
ans+=dp[x];
rep(i,,){
if(t[x].son[i])dfs(t[x].son[i],x);
}
vis[x]--;
cx=t[x].ff;
while(cnt--){
vis[cx]--;cx=t[cx].ff;
}
} void solve(){
dfs(,),dfs(,);
printf("Case #%d: %lld\n",cat++,ans);
}
}a;
int main(){
int T;
cin>>T;
while(T--){
scanf("%s",s+);
int len=strlen(s+);
a.init();
rep(i,,len){
a.extend(s[i]-'a',i);
}
a.solve();
} }

2019牛客暑期多校训练营(第六场)Palindrome Mouse 回文树+dfs的更多相关文章

  1. 2019牛客暑期多校训练营(第一场)I dp+线段树

    题意 给出n个点,每个点有a,b两个属性,让你从左下角到右上角划一条线,线的左边每个点的贡献是\(a_i\),线的右边每个点的贡献是\(b_i\),使得两部分的总和最大. 分析 找一条折线将点分割开, ...

  2. 2019牛客暑期多校训练营(第六场)C - Palindrome Mouse (回文自动机)

    https://ac.nowcoder.com/acm/contest/886/C 题意: 给出一个串A , 集合S里面为A串的回文字串 , 现在在集合S里面找出多少对(a,b),b为a的字串 分析: ...

  3. 2019牛客暑期多校训练营(第二场)E.MAZE(线段树+dp)

    题意:给你一个n*m的矩阵 你只能向左向右相下走 有两种操作 q次询问 一种是把一个单位翻转(即可走变为不可走 不可走变为可走) 另一种是询问从(1,x) 走到 (n,y)有多少种方案 思路:题目n为 ...

  4. 2019牛客暑期多校训练营(第六场)J Upgrading Technology

    传送门 题意: 就是给你n个技能,每个技能最高升到m级,每升一级就是耗费Cij钱,这个Cij可能是负的,如果所有技能都升到或者说超过j等级,就会获得Dj钱,这个Dj也有可能是负值,让你求你最多得到多少 ...

  5. 2019牛客暑期多校训练营(第九场)A:Power of Fibonacci(斐波拉契幂次和)

    题意:求Σfi^m%p. zoj上p是1e9+7,牛客是1e9:  对于这两个,分别有不同的做法. 前者利用公式,公式里面有sqrt(5),我们只需要二次剩余求即可.     后者mod=1e9,5才 ...

  6. 2019牛客暑期多校训练营(第一场)A题【单调栈】(补题)

    链接:https://ac.nowcoder.com/acm/contest/881/A来源:牛客网 题目描述 Two arrays u and v each with m distinct elem ...

  7. 2019牛客暑期多校训练营(第一场) B Integration (数学)

    链接:https://ac.nowcoder.com/acm/contest/881/B 来源:牛客网 Integration 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 5242 ...

  8. 2019牛客暑期多校训练营(第一场) A Equivalent Prefixes ( st 表 + 二分+分治)

    链接:https://ac.nowcoder.com/acm/contest/881/A 来源:牛客网 Equivalent Prefixes 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/ ...

  9. 2019牛客暑期多校训练营(第二场)F.Partition problem

    链接:https://ac.nowcoder.com/acm/contest/882/F来源:牛客网 Given 2N people, you need to assign each of them ...

  10. 2019牛客暑期多校训练营(第一场)A Equivalent Prefixes(单调栈/二分+分治)

    链接:https://ac.nowcoder.com/acm/contest/881/A来源:牛客网 Two arrays u and v each with m distinct elements ...

随机推荐

  1. OpenGL中的空间变换

    OpenGL中的空间变换          在使用OpenGL的三维虚拟程序中.当我们指定了模型的顶点之后.在屏幕上显示它们之前,一共会发生3种类型的变换:视图变换.模型变换.投影变换.        ...

  2. Python之删除字符串中不需要的字符

    简单的 str="---你好=====" print(str.strip("-=")) # 你好 从文件中读取多行数据,可以用生成器表达式 with open( ...

  3. LeetCode Array Easy 27. Remove Element 解题

    Given an array nums and a value val, remove all instances of that value in-place and return the new ...

  4. 使用androidstudio时遇到的一些小错误

    1 路径名字中不能有汉字  报如下错误:Error:(1, 0) Your project path contains non-ASCII characters. This will most lik ...

  5. 配置基于python的VIM环境

    配置基于python的VIM环境 安装插件管理工具 为防止过多插件管理的麻烦,首先安装vim的插件管理工具Vundle.vundle本身的github软件已经有相关的中文文档,地址如下: vundle ...

  6. redis集群扩容(添加新节点)

    一.创建节点(接上文) 1.在H1服务器/root/soft目录下创建7002目录 2.将7001目录的配置文件redis.conf拷贝到7002,并修改配置文件的端口 3.进入 redis-5.0. ...

  7. 61. File类

    IO技术主要作用是解决设备与设备之间的数据传输问题.比如:硬盘---->内存     内存的数据---->硬盘上    把硬盘的数据------>内存中 IO技术的应用场景:     ...

  8. MySql中创建用户,授权

    第一天搞MySql好多东西都不会,幸好有网络的强大资源,首先需要注意的是任何一条sql语句都是要以分号结尾的,不然很是蛋疼的 1.新建用户. //登录MYSQL @>mysql -u root  ...

  9. 视觉里程计:2D-2D 对极几何、3D-2D PnP、3D-3D ICP

    参考链接:https://mp.weixin.qq.com/s/89IHjqnw-JJ1Ak_YjWdHvA #include <iostream> #include <opencv ...

  10. 炼数成金数据分析课程---10、python中如何画图

    炼数成金数据分析课程---10.python中如何画图 一.总结 一句话总结: 主要matplotlib库,pandas中也可以画一些基础图 大纲+实例快速学习法 1.matplotlib的最简单画图 ...