题目链接

传送门

题意

问\(s\)串中所有本质不同的回文子串中有多少对回文子串满足\(a\)是\(b\)的子串。

思路

参考代码:传送门

本质不同的回文子串肯定是要用回文树的啦~

在建好回文树后分别对根结点为\(0,1\)的子树进行\(dfs\),处理出以每个结点为根结点的子树的大小\(sz\)(也就是说有多少个回文子串以其为中心)和其\(dfs\)序,回文子串包含除了作为其他回文子串的中心被包含外,还可以不作为中心被包含,而这一部分则需要靠回文树的\(fail\)数组来进行处理。

我们先用\(vector\)存下有多少个结点的\(fail\)数组指向\(i\),然后把这些结点按照其对应的回文串长度进行排序,用树状数组来防止去重,加入这个结点对应的\(dfs\)序没被覆盖,那么就加上这个结点的\(sz\),否则就不加。此处举个例子帮助理解:\(cac,cedcacdec\)的\(fail\)数组都指向了\(c\),但是\(cedcacdec\)是\(cac\)子树中的结点,我们在加\(cac\)的时候已经把\(cedcacdec\)的贡献计算过了,如果再加一次就会重复,因此如果某个结点的\(dfs\)序被前面长度短的结点包含过,那么就不用加进答案中。

代码

#include <set>
#include <map>
#include <deque>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <bitset>
#include <cstdio>
#include <string>
#include <vector>
#include <cassert>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std; typedef long long LL;
typedef pair<LL, LL> pLL;
typedef pair<LL, int> pLi;
typedef pair<int, LL> pil;;
typedef pair<int, int> pii;
typedef unsigned long long uLL; #define lson (rt<<1),L,mid
#define rson (rt<<1|1),mid + 1,R
#define lowbit(x) x&(-x)
#define name2str(name) (#name)
#define bug printf("*********\n")
#define debug(x) cout<<#x"=["<<x<<"]" <<endl
#define FIN freopen("/home/dillonh/CLionProjects/Dillonh/in.txt","r",stdin)
#define IO ios::sync_with_stdio(false),cin.tie(0) const double eps = 1e-8;
const int mod = 1000000007;
const int maxn = 100000 + 7;
const double pi = acos(-1);
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3fLL; int _, n, cnt;
char s[maxn];
vector<int> vec[maxn];
int sz[maxn], ls[maxn], rs[maxn], vis[maxn]; struct PAM {
//len数组表示以i为结尾的最长回文子串长度
//tot为结点数,lst为上一个字符加的位置
int N;
int str[maxn];
int ch[maxn][30], fail[maxn], len[maxn], cnt[maxn], tot, lst;
void init() {
for(int i = 0; i <= n + 1; ++i) {
cnt[i] = len[i] = fail[i] = 0;
for(int j = 0; j <= 26; ++j) ch[i][j] = 0;
}
N = lst = 0; tot = 1; fail[0] = fail[1] = 1; len[1] = -1;
}
inline void add(int c) {
int p = lst;
str[++N] = c;
while(str[N - len[p] - 1] != str[N]) p = fail[p];
if(!ch[p][c]) {
int now = ++tot, k = fail[p];
len[now] = len[p] + 2;
while(str[N - len[k] - 1] != str[N]) k = fail[k];
fail[now] = ch[k][c]; ch[p][c] = now;
}
lst = ch[p][c]; cnt[lst]++;
}
inline void solve() {
for(int i = tot; i; i--) {
cnt[fail[i]] += cnt[i];
}
}
}pam; int tree[maxn]; void add(int x, int val) {
while(x < maxn) {
tree[x] += val;
x += lowbit(x);
}
} int query(int x) {
int ans = 0;
while(x) {
ans += tree[x];
x -= lowbit(x);
}
return ans;
} void dfs(int u) {
sz[u] = 1;
ls[u] = ++cnt;
for(int i = 1; i <= 26; ++i) {
if(pam.ch[u][i]) {
dfs(pam.ch[u][i]);
sz[u] += sz[pam.ch[u][i]];
}
}
rs[u] = cnt;
} int main() {
#ifndef ONLINE_JUDGE
FIN;
#endif
scanf("%d", &_);
for(int __ = 1; __ <= _; ++__) {
scanf("%s", s + 1);
n = strlen(s + 1);
pam.init();
for(int i = 1; i <= n; ++i) pam.add(s[i] - 'a' + 1);
cnt = 0;
dfs(1);
dfs(0);
LL ans = 0;
for(int i = 2; i <= pam.tot; ++i) vec[i].clear();
for(int i = 2; i <= pam.tot; ++i) {
if(pam.fail[i] >= 2) vec[pam.fail[i]].emplace_back(i);
}
for(int i = 2; i <= pam.tot; ++i) {
vec[i].emplace_back(i);
sort(vec[i].begin(), vec[i].end(), [](int x, int y) {return pam.len[x] < pam.len[y];});
LL sum = 0;
for(int j = 0; j < (int)vec[i].size(); ++j) {
int u = vec[i][j];
if(query(ls[u]) == 0) {
sum += sz[u];
add(ls[u], 1);
add(rs[u] + 1, -1);
vis[j] = 1;
}
}
ans += sum - 1;
for(int j = 0; j < (int)vec[i].size(); ++j) {
if(!vis[j]) continue;
int u = vec[i][j];
add(ls[u], -1);
add(rs[u] + 1, 1);
vis[j] = 0;
}
}
printf("Case #%d: %lld\n", __, ans);
}
return 0;
}

Palindrome Mouse(2019年牛客多校第六场C题+回文树+树状数组)的更多相关文章

  1. 2019牛客多校第八场 F题 Flowers 计算几何+线段树

    2019牛客多校第八场 F题 Flowers 先枚举出三角形内部的点D. 下面所说的旋转没有指明逆时针还是顺时针则是指逆时针旋转. 固定内部点的答案的获取 anti(A)anti(A)anti(A)或 ...

  2. Distance(2019年牛客多校第八场D题+CDQ+树状数组)

    题目链接 传送门 思路 这个题在\(BZOJ\)上有个二维平面的版本(\(BZOJ2716\)天使玩偶),不过是权限题因此就不附带链接了,我也只是在算法进阶指南上看到过,那个题的写法是\(CDQ\), ...

  3. 2019年牛客多校第四场 B题xor(线段树+线性基交)

    题目链接 传送门 题意 给你\(n\)个基底,求\([l,r]\)内的每个基底是否都能异或出\(x\). 思路 线性基交板子题,但是一直没看懂咋求,先偷一份咖啡鸡板子写篇博客吧~ 线性基交学习博客:传 ...

  4. generator 1(2019年牛客多校第五场B题+十进制矩阵快速幂)

    目录 题目链接 思路 代码 题目链接 传送门 思路 十进制矩阵快速幂. 代码 #include <set> #include <map> #include <deque& ...

  5. Find the median(2019年牛客多校第七场E题+左闭右开线段树)

    题目链接 传送门 题意 每次往集合里面添加一段连续区间的数,然后询问当前集合内的中位数. 思路 思路很好想,但是卡内存. 当时写的动态开点线段树没卡过去,赛后机房大佬用动态开点过了,\(tql\). ...

  6. Explorer(2019年牛客多校第八场E题+线段树+可撤销并查集)

    题目链接 传送门 题意 给你一张无向图,每条边\(u_i,v_i\)的权值范围为\([L_i,R_i]\),要经过这条边的条件是你的容量要在\([L_i,R_i]\),现在问你你有多少种容量使得你可以 ...

  7. 2019年牛客多校第三场 F题Planting Trees(单调队列)

    题目链接 传送门 题意 给你一个\(n\times n\)的矩形,要你求出一个面积最大的矩形使得这个矩形内的最大值减最小值小于等于\(M\). 思路 单调队列滚动窗口. 比赛的时候我的想法是先枚举长度 ...

  8. [题解]Shorten IPv6 Address-模拟(2019牛客多校第六场B题)

    题目链接:https://ac.nowcoder.com/acm/contest/886/B 题意: 您将获得一个IPv6地址,该地址是128位二进制字符串.请根据以下规则确定其最短的表示: 以十六进 ...

  9. 2020牛客多校第八场K题

    __int128(例题:2020牛客多校第八场K题) 题意: 有n道菜,第i道菜的利润为\(a_i\),且有\(b_i\)盘.你要按照下列要求给顾客上菜. 1.每位顾客至少有一道菜 2.给顾客上菜时, ...

随机推荐

  1. Windows下找到JVM占用资源高的线程

    与linux下top命令直接显示进程下线程资源占用不同,Windows下默认任务管理器只能显示出进程的资源占用,jconsle等工具也只能显示出java进程资源占用,无法显示出进程能具体线程的资源占用 ...

  2. 第02组 Beta冲刺(3/4)

    队名:十一个憨批 组长博客 作业博客 组长黄智 过去两天完成的任务:了解整个游戏的流程 GitHub签入记录 接下来的计划:继续完成游戏 还剩下哪些任务:完成游戏 燃尽图 遇到的困难:没有美术比较好的 ...

  3. [LeetCode] 926. Flip String to Monotone Increasing 翻转字符串到单调递增

    A string of '0's and '1's is monotone increasing if it consists of some number of '0's (possibly 0), ...

  4. DVWA XSS (DOM) 通关教程

    DOM,全称Document Object Model,是一个平台和语言都中立的接口,可以使程序和脚本能够动态访问和更新文档的内容.结构以及样式. DOM型XSS其实是一种特殊类型的反射型XSS,它是 ...

  5. Harbor 忘记密码

    Harbor密码重置 01,登入到harbor容器里面的数据库上 docker exec -it harbor-db /bin/bash 02,登入数据库 psql -h postgresql -d ...

  6. Spring 常犯的十大错误,这坑你踩过吗?

    阅读本文大概需要 9 分钟. 1.错误一:太过关注底层 我们正在解决这个常见错误,是因为 “非我所创” 综合症在软件开发领域很是常见.症状包括经常重写一些常见的代码,很多开发人员都有这种症状. 虽然理 ...

  7. Redis快速入门及使用

    概述 redis是一种支持分布式的nosql数据库,他的数据是保存在内存中,同时redis可以定时把内存数据同步到磁盘,即可以将数据持久化,并且他比memcached支持更多的数据结构(string, ...

  8. String.format方法使用-浅析(转)

    转自  https://blog.csdn.net/u010137760/article/details/82869637 1.代码中简单使用2.源码调用的方法3.相关类-Formatter3.1可选 ...

  9. linux 查看用户列表

    cat /etc/passwd|grep -v nologin|grep -v halt|grep -v shutdown|awk -F":" '{ print $1"| ...

  10. ab小工具的Failed requests多的问题

    ab小工具的Failed requests多的问题 这个是PHP返回的length不一致造成的 是ab的bug 所以不用理会.. 测试并发写100就行了 一般100没错误