Solution -「NOI.AC 省选膜你赛」T2
这道题就叫 T2 我有什么办法www
题目
题意简述
给定一个字符串 \(s\),其长度为 \(n\),求无序子串对 \((u,v)\) 的个数,其中 \((u,v)\) 满足 \(u,v\) 均为回文串且出现位置相交。
数据规模
\(n\le2\times10^6\),字符集为小写字母(于是测试数据里有神奇的'{'字符。
题解
难得的水题呐!
正难则反,首先求出总的回文子串对数,再减去出现位置不交的对数。
对于前者,用 Manacher 或者 PAM 都可以轻松求出,这里用的 PAM。
对于后者,记 \(f(i)\) 为原串中以 \(i\) 结尾的回文串个数,\(g(i)\) 为 \(s[i..n]\) 中的回文子串个数。那么不交的回文子串对的对数为:
\]
\(f\) 和 \(g\) 亦能用 PAM 求出,这道题就解决啦~
最后测试数据出锅,AC 失败qwq。
代码
#include <cstdio>
#include <cstring>
#include <algorithm>
const int MAXN = 2e6, MOD = 998244353, INV2 = 499122177;
char s[MAXN + 5];
int preend[MAXN + 5], sufend[MAXN + 5];
class PalindromeAutomaton {
private:
int cnt, lst, ch[MAXN + 5][26], len[MAXN + 5], link[MAXN + 5], dep[MAXN + 5];
public:
PalindromeAutomaton (): cnt ( 1 ), lst ( 1 ), len { 0, -1 }, link { 1, 0 } {}
inline void clear () {
for ( int i = 0; i <= cnt; ++ i ) {
dep[i] = link[i] = len[i] = 0;
for ( int j = 0; j < 26; ++ j ) ch[i][j] = 0;
}
cnt = lst = 1, len[1] = -1, link[0] = 1;
}
inline int build ( const char* str, int* endcnt ) {
int ret = 0;
for ( int i = 1; str[i]; ++ i ) {
int cid = str[i] - 'a', p = lst;
for ( ; str[i] ^ str[i - len[p] - 1]; p = link[p] );
if ( ! ch[p][cid] ) {
int cur = ++ cnt, q = link[p]; len[cur] = len[p] + 2;
for ( ; str[i] ^ str[i - len[q] - 1]; q = link[q] );
dep[cur] = dep[link[cur] = ch[q][cid]] + 1, ch[p][cid] = cur;
}
ret = ( ret + ( endcnt[i] = dep[lst = ch[p][cid]] ) ) % MOD;
}
return ret;
}
} pam;
int main () {
scanf ( "%s", s + 1 );
int ans = pam.build ( s, preend ), n = strlen ( s + 1 );
ans = ( ans * ( ans - 1ll ) % MOD * INV2 % MOD + MOD ) % MOD;
pam.clear (), std :: reverse ( s + 1, s + n + 1 );
pam.build ( s, sufend ), std :: reverse ( sufend + 1, sufend + n + 1 );
for ( int i = n - 1; i; -- i ) sufend[i] = ( sufend[i + 1] + sufend[i] ) % MOD;
for ( int i = 1; i < n; ++ i ) ans = ( ( ans - 1ll * preend[i] * sufend[i + 1] % MOD ) % MOD + MOD ) % MOD;
printf ( "%d\n", ans );
return 0;
}
Solution -「NOI.AC 省选膜你赛」T2的更多相关文章
- Solution -「NOI.AC 省选膜你赛」array
题目 题意简述 维护一个长度为 \(n\) 的序列 \(\{a_n\}\),并给出 \(q\) 个操作: 将下标为 \(x\) 的数修改为 \(y\). 给定 \(l,r,k\),求最大的 \(m ...
- Solution -「NOI.AC 省选膜你赛」寄蒜几盒
题目 题意简述 给定一个含有 \(n\) 个顶点的凸多边形( \(n\) 是偶数),对于每一对相对的边(即中间有 \(\frac{n}2-1\) 条其它边),延长它们以将平面分割为多块,并把包含原 ...
- Solution -「NOI.AC 省选膜你赛」union
题目 题意简述 给定两颗树 \(A,B\),\(A\) 中的任一结点 \(u\) 与 \(B\) 中的任一结点 \(v\) 都有一个关系值 \(f(u,v)\),初始为 \(0\).再给出 \(q ...
- cdcqの省选膜你赛
cdcqの省选膜你赛 比赛当天因为在杠hnoi2016的大数据结构没有参加,今天补了一下.挺好玩的虽然不看一句话题意的话真的卡读题 此生无悔入东方,来世愿生幻想乡 2651. 新史「新幻想史 -现代史 ...
- Solution -「NOI 2021」「洛谷 P7740」机器人游戏
\(\mathcal{Description}\) Link. 自己去读题面叭~ \(\mathcal{Solution}\) 首先,参悟[样例解释 #2].一种暴力的思路即为钦定集合 \ ...
- Solution -「NOI 2020」「洛谷 P6776」超现实树
\(\mathcal{Description}\) Link. 对于非空二叉树 \(T\),定义 \(\operatorname{grow}(T)\) 为所有能通过若干次"替换 \( ...
- Solution -「NOI 模拟赛」彩色挂饰
\(\mathcal{Description}\) 给定一个含 \(n\) 个点 \(m\) 条边的简单无向图,设图中最大点双的大小为 \(s\),则保证 \(s\le6\).你将要用 \(k\) ...
- Solution -「NOI 模拟赛」出题人
\(\mathcal{Description}\) 给定 \(\{a_n\}\),求一个 \(\{b_{n-1}\}\),使得 \(\forall x\in\{a_n\},\exists i,j\ ...
- Solution -「NOI 2016」「洛谷 P1587」循环之美
\(\mathcal{Description}\) Link. 给定 \(n,m,k\),求 \(x\in [1,n]\cap\mathbb N,y\in [1,m]\cap \mathbb ...
随机推荐
- asyncio异步编程
1. 协程 协程不是计算机提供,程序员认为创造 协程(Coroutine),也可以被称为微线程,是一种用户态内的上下文切换技术,其实就是一个线程实现代码块相互切换执行.例如: def func1(): ...
- SpringBoot学习笔记三之表述层
注:图片如果损坏,点击文章链接:https://www.toutiao.com/i6803355920697917965/ 首先配置learn-admin-webui中的web.xml文件 配置Con ...
- 解决maven每次更新都编程java1.5
Maven: 每次更新Maven Project ,JAVA 版本都变为1.5 本文转载自:http://www.cnblogs.com/Hxinguan/p/6132446.html 问题: 1.创 ...
- vue 自动生成菜单
import constant from './const' export function getRouters (files) { let filenames = files.keys() let ...
- javascript中什么时候要用\来转义
1.定义字符串的单引号或双引号里的同符号或字符串内回车换行,比如A: a = "<a href=\"...\">a</a>"; B: a ...
- GoLang设计模式19 - 桥接模式
桥接模式是一种结构型设计模式,通过桥接模式可以将抽象部分和它的实现部分分离.这看着有点儿奇怪,接下来会作详细说明. 桥接模式建议将一个较大的类拆分成两中角色. 抽象角色 - 抽象角色是一个接口.它的子 ...
- github与gitlab创建新仓库
github创建新仓库 然后根据下一页的命令提示进行即可 gitlab创建新仓库 git init git remote add origin git@***.***.**.**:user/proje ...
- 【解决了一个小问题】golang samara的kafka客户端中使用错误版本号导致初始化失败
发现在如下代码中存储kafka生产者初始化失败: config.Version = sarama.V0_10_2_1 //V2_2_0_0 producer, err := sarama.NewSyn ...
- 【记录一个问题】redis中执行事务出现错误“EXECABORT Transaction discarded because of previous errors”
执行事务的大致代码如下: redisClient := GetRedisClient() pipe := redisClient.TxPipeline() err := pipe.ZAdd(k, ar ...
- 【小记录】cv::cuda::Stream中取出cudaStream_t并用于核函数的计算
以下是找到的代码 1 cv::cuda::Stream stream; 2 cudaStream_t s = cv::cuda::StreamAccessor::getStream(stream); ...