题目链接

传送门

题意

问\(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. linux中sleep函数的使用和总结

    在linux编程中,有时候会用到定时功能,常见的是用sleep(time)函数来睡眠time秒:但是这个函数是可以被中断的,也就是说当进程在睡眠的过程中,如果被中断,那么当中断结束回来再执行该进程的时 ...

  2. [LeetCode] 785. Is Graph Bipartite? 是二分图么?

    Given an undirected graph, return true if and only if it is bipartite. Recall that a graph is bipart ...

  3. dogcom在openwrt上的使用

    前提,先配置并运行mentohust(作为802.1x认证) 1,取得编译完成的可执行文件(可先在虚拟机里测试) 2,上传到路由器 3,把dogcom主程序和配置文件放在/etc/storage/do ...

  4. 用 cgroups 管理 cpu 资源

    转自:http://xiezhenye.com/2013/10/用-cgroups-管理-cpu-资源.html 这回说说怎样通过 cgroups 来管理 cpu 资源.先说控制进程的 cpu 使用. ...

  5. 第09组 Beta冲刺(3/5)

    队名:观光队 链接 组长博客 作业博客 组员实践情况 王耀鑫 过去两天完成了哪些任务 文字/口头描述 学习 展示GitHub当日代码/文档签入记录 接下来的计划 完成短租车,页面美化 还剩下哪些任务 ...

  6. 第01组 Beta冲刺(5/5)

    队名:007 组长博客: https://www.cnblogs.com/Linrrui/p/12031875.html 作业博客: https://edu.cnblogs.com/campus/fz ...

  7. NOI 2019 退役记

    非常抱歉,因为不退役了,所以这篇退役记鸽了.

  8. tecplot——Fluent重叠网格解决方案

    算例来源:http://blog.sina.com.cn/s/blog_af99efb50102xoh3.html 受上篇博文的启发,在tecplot当中也能采用类似的方法处理Fluent的重叠网格计 ...

  9. Java软件生产监控工具Btrace的使用

    Btrace BTrace是sun公司推出的一款Java 动态.安全追踪(监控)工具,可以在不用重启的情况下监控系统运行情况,方便的获取程序运行时的数据信息,如方法参数.返回值.全局变量和堆栈信息等, ...

  10. 论文阅读: Direct Monocular Odometry Using Points and Lines

    Direct Monocular Odometry Using Points and Lines Abstract 大多数VO都用点: 特征匹配 / 基于像素intensity的直接法关联. 我们做了 ...