题目链接

传送门

题意

给你一个串串,问你有多少对回文串相交。

思路

由于正着做不太好算答案,那么我们考虑用总的回文对数减去不相交的回文对数。

而不相交的回文对数可以通过计算以\(i\)为右端点的回文串的个数\(\times\)以\(i+1,i+2\dots,n\)为左端点的回文串的个数计算得到。

以\(i\)为右端点的回文串的个数可以直接用回文树\(O(n)\)求出来,以\(i\)为左端点的回文串的个数反着求一遍即可。

不过要注意本题由于数据范围比较大,使用邻接矩阵会导致\(MLE\),因此需要使用邻接矩阵来代替。

代码实现如下

#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
#define rson rt<<1|1
#define lowbit(x) x&(-x)
#define name2str(name) (#name)
#define bug printf("*********\n")
#define debug(x) cout<<#x"=["<<x<<"]" <<endl
#define FIN freopen("in.txt","r",stdin)
#define IO ios::sync_with_stdio(false),cin.tie(0) const double eps = 1e-8;
const int mod = 51123987;
const int maxn = 2e6 + 7;
const double pi = acos(-1);
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3fLL; int n;
LL ans, tmp;
LL sum[maxn];
char s[maxn]; struct PAM {
//len数组表示以i为结尾的最长回文子串长度
//tot为结点数,lst为上一个字符加的位置
int N, totedge;
int str[maxn], head[maxn];
int fail[maxn], len[maxn], cnt[maxn], num[maxn], tot, lst;
void init() {
for(int i = 0; i <= n + 1; ++i) {
head[i] = -1;
cnt[i] = len[i] = fail[i] = num[i] = 0;
}
totedge = N = lst = 0; tot = 1; fail[0] = fail[1] = 1; len[1] = -1;
} struct edge {
int v, w, next;
}ed[maxn]; void add(int u, int v, int w) {
ed[totedge].v = v;
ed[totedge].w = w;
ed[totedge].next = head[u];
head[u] = totedge++;
} inline int fi(int u, int v) {
for(int i = head[u]; ~i; i = ed[i].next) {
if(ed[i].v == v) return ed[i].w;
}
return 0;
} inline int add(int c) {
int p = lst;
str[++N] = c;
while(str[N - len[p] - 1] != str[N]) p = fail[p];
if(!(lst = fi(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] = fi(k, c);
add(p, c, now);
num[now] = num[fail[now]] + 1;
lst = now;
}
cnt[lst]++;
return num[lst];
}
inline void solve() {
for(int i = tot; i; i--) {
cnt[fail[i]] += cnt[i];
(tmp += cnt[i]) %= mod;
}
}
}pam; int main() {
#ifndef ONLINE_JUDGE
FIN;
#endif
scanf("%d", &n);
scanf("%s", s + 1);
pam.init();
for(int i = n; i >= 1; --i) {
sum[i] = (sum[i+1] + pam.add(s[i] - 'a' + 1)) % mod;
}
pam.init();
for(int i = 1; i <= n; ++i) {
int cnt = pam.add(s[i] - 'a' + 1);
(ans += 1LL * cnt * sum[i+1] % mod) %= mod;
}
pam.solve();
printf("%lld\n", (((1LL * tmp * (tmp-1) / 2 % mod) - ans) % mod + mod) % mod);
return 0;
}

Palisection(Codeforces Beta Round #17E+回文树)的更多相关文章

  1. Codeforces 932G Palindrome Partition - 回文树 - 动态规划

    题目传送门 通往???的传送点 通往神秘地带的传送点 通往未知地带的传送点 题目大意 给定一个串$s$,要求将$s$划分为$t_{1}t_{2}\cdots t_{k}$,其中$2\mid k$,且$ ...

  2. Codeforces 932G Palindrome Partition 回文树+DP

    题意:给定一个串,把串分为偶数段 假设分为$s_1,s_2,s_3....s_k$ 求满足$ s_1=s_k,s_2=s_{ k-1 }... $的方案数模$10^9+7$ $|S|\leq 10^6 ...

  3. Codeforces Beta Round #19D(Points)线段树

    D. Points time limit per test 2 seconds memory limit per test 256 megabytes input standard input out ...

  4. CodeForces 17E Palisection(回文树)

    E. Palisection time limit per test 2 seconds memory limit per test 128 megabytes input standard inpu ...

  5. 【CF17E】Palisection(回文树)

    [CF17E]Palisection(回文树) 题面 洛谷 题解 题意: 求有重叠部分的回文子串对的数量 所谓正难则反 求出所有不重叠的即可 求出以一个位置结束的回文串的数量 和以一个位置为开始的回文 ...

  6. CF17E Palisection(manacher/回文树)

    CF17E Palisection(manacher/回文树) Luogu 题解时间 直接正难则反改成求不相交的对数. manacher求出半径之后就可以差分搞出以某个位置为开头/结尾的回文串个数. ...

  7. Codeforces.GYM100548G.The Problem to Slow Down You(回文树)

    题目链接 \(Description\) 给定两个串\(S,T\),求两个串有多少对相同回文子串. \(|S|,|T|\leq 2\times 10^5\). \(Solution\) 好菜啊QAQ ...

  8. CF17E Palisection(回文树)

    题意翻译 给定一个长度为n的小写字母串.问你有多少对相交的回文子 串(包含也算相交) . 输入格式 第一行是字符串长度n(1<=n<=2*10^6),第二行字符串 输出格式 相交的回文子串 ...

  9. Palindrome Partition CodeForces - 932G 回文树+DP+(回文后缀的等差性质)

    题意: 给出一个长度为偶数的字符串S,要求把S分成k部分,其中k为任意偶数,设为a[1..k],且满足对于任意的i,有a[i]=a[k-i+1].问划分的方案数. n<=1000000 题解: ...

随机推荐

  1. python 使用nmap 模块

    官网 https://pypi.org/project/python-nmap/ >>> import nmap>>> nm = nmap.PortScannerS ...

  2. Java集合详解2:一文读懂Queue和LinkedList

    <Java集合详解系列>是我在完成夯实Java基础篇的系列博客后准备开始写的新系列. 这些文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查 ...

  3. react-native 设置启动模拟器

    react-native 设置启动模拟器 查看iOS可选设备: xcrun simctl list devices iPhone7 Plus启动(下次启动会默认使用最后一次选择设备,直接启动npx r ...

  4. 那些陌生的C++关键字

    C/C++中的关键字如下: 下面我们主要介绍一些比较陌生的关键字,一些常见的关键字这里就不再赘述了. 1.asm asm 是一个语句的分隔符,不能单独出现,必须接汇编指令.一组被大括号包含的指令或一对 ...

  5. linux 操作文件夹

    创建文件夹[mkdir] 一.mkdir命令使用权限 所有用户都可以在终端使用 mkdir 命令在拥有权限的文件夹创建文件夹或目录. 二.mkdir命令使用格式 格式:mkdir [选项] DirNa ...

  6. [转帖]中国 GPL 诉讼第一案:关于 GPL 问题的探讨

    中国 GPL 诉讼第一案:关于 GPL 问题的探讨 https://linux.cn/article-11683-1.html 2019 年 11 月初,数字天堂(北京)网络技术有限公司(下称:数字天 ...

  7. 生成Makefile文件全过程

    [1]生成Makefile文件全过程 整体流程如下图: 注意:以下文件根目录为testmake(任意位置新建即可) (1)测试程序 1.1 建立两个目录:mkdir include source 1. ...

  8. MVVM模式理解(转)

    原文https://www.cnblogs.com/goloving/p/8520030.html MVVM 是Model-View-ViewModel 的缩写,它是一种基于前端开发的架构模式,其核心 ...

  9. golang ---rune与byte

    golang内置类型有rune类型和byte类型. rune类型的底层类型是int32类型,而byte类型的底层类型是int8类型,这决定了rune能比byte表达更多的数. 在unicode中,一个 ...

  10. 【WPF】2、美化控件

    控件有默认样式,但是有时候默认样式并不够用,就需要美化. 1.常用的方法是美术出图,直接贴图进去,效果又好又简单(对程序来说). 用图片有三种方式:设置控件背景图片.设置控件内容为图片和直接使用图片做 ...