首页 > 其他分享 >题解:CF1827C Palindrome Partition

题解:CF1827C Palindrome Partition

时间:2024-12-03 17:12:21浏览次数:11  
标签:Palindrome int 题解 len MAXN CF1827C cv dp 回文

CF1827C Palindrome Partition 题解

题面

题目传送门

称一个字符串是好的,当且仅当它是一个长度为偶数的回文串或由若干长度为偶数的回文串拼接而成。

给定一个长度为 \(n\) 的字符串 \(s\),求有多少 \(s\) 的子串是好的。

$ 1 \le n \le 5 \cdot 10^5\(,\)s$ 仅包含小写字母。

与 CSP-S 2023 T2 的区别

千万不要说这两题重了,免得别人来笑话。

举一个例子,abbcca,可以思考一下。

分析

那么这题多半是只能老老实实去找回文串。考虑使用回文树

先来分析回文串的性质。

  • 设 \(s[l,r]\) 为回文串,若 \(s[x,r]\) 也为回文串(\(\left\lfloor \frac{l+r+1}{2}\right\rfloor \le x \le r\))。
  • 则 \(s[l,l+(r-x+1)-1]\) 也为回文串(因为整体回文,所以右边会问则左边也回文)。
  • 则 \(s[l+(r-x+1),x-1]\) 也为回文串(因为整体回文)。

如果通过第一个假设,判断 \(s[l,r]\) 是好的就不需要判断 \(s[l,r]\) 是否回文,只用判断它内部是否可以组成。

思路

我们知道在字符串位置 \(i\),在回文树位置 \(j\),只用不断跳后缀链接,设当前位置回文串的长度为 \(l\),则 \(s[i-l+1,i]\) 为回文串。

设对于所有 \(l\) 为偶数,组成一个序列 \(L_1<L_2<L_3<\cdots<L_k\),那么 \(s[i-L_x+1,i]\) (\(2 \le x \le k\))必定可以被除自己的回文串组成(通过分析容易知道)。

那么我们只用对于每个 \(i\) 找到 \(L_1\)(可以用路径压缩来解决满足复杂度要求),则 \(dp_i=dp_{L_1}+1\),若没有 \(L_1\),则 \(dp_i=0\)。

最后答案为 \(\sum_{x=1}^{n}{dp_x}\)。

时间复杂度 \(O(n \log n)\),瓶颈在找到 \(L_1\)。

Code

#include <bits/stdc++.h>

using namespace std;
using LL = long long;
using Pair = pair<LL, LL>;

const int MAXN = 1e6 + 3;

int n;
string s;
int trie[MAXN][26], cv = 1, len[MAXN], _len[MAXN], pos[MAXN]/*原串中出现位置*/, nxt[MAXN]/*后缀链接*/;
int fa[MAXN];
LL dp[MAXN], ans = 0;

int Getf(int x){
  if(fa[x] <= 1|| fa[x] == x || Getf(fa[x]) == 0 || _len[Getf(fa[x])] == 0){
    return (len[x] % 2 == 0 ? fa[x] = x : fa[x] = 0);
  }else return fa[x] = Getf(fa[x]);
}

int main(){
  ios::sync_with_stdio(0), cin.tie(0);
  int T;
  cin >> T;
  while(T--){
    cin >> n >> s, s = " " + s;
    for(int i = 0; i <= cv; i++){
      for(int col = 0; col < 26; col++) trie[i][col] = 0;
    }
    cv = 1;
    ans = 0;
    _len[0] = len[0] = -1, nxt[0] = 0, _len[1] = len[1] = 0, nxt[1] = 0;
    for(int i = 1, j = 1 /* i-1 的后缀的最长回文后缀对应回文树上的节点编号 */; i <= n; i++){
      while(s[i] != s[i - len[j] - 1]) j = nxt[j];
      if(!trie[j][s[i] - 'a']){
        trie[j][s[i] - 'a'] = ++cv;
        _len[cv] = len[cv] = len[j] + 2;
        pos[cv] = i - len[cv] + 1;
        for(int &k = (nxt[cv] = nxt[j]); s[i] != s[i - len[k] - 1]; k = nxt[k]);
        // 也可以写成 for(int &k = nxt[cv] = nxt[j]; s[i] != s[i - len[k] - 1]; k = nxt[k]);

        if(len[cv] > 1) fa[cv] = nxt[cv] = trie[nxt[cv]][s[i] - 'a'];
        else fa[cv] = nxt[cv] = 1;
      }
      j = trie[j][s[i] - 'a'];
      if(Getf(j) != 0) _len[j] = _len[Getf(j)];
      else _len[j] = 0;
      dp[i] = (_len[j] == 0 ? 0 : dp[i - _len[j]] + 1), ans += dp[i];
    }
    cout << ans << "\n";
  }
  return 0;
}
/*
6
abaaba
1 2 1 1 1
1 2 0 1 1**
2 3 1 1 1
2 3 0 1 1**
3 4 2 2 3
3 4 0 2 3**
4 5 2 2 2
*/

标签:Palindrome,int,题解,len,MAXN,CF1827C,cv,dp,回文
From: https://www.cnblogs.com/huangqixuan/p/18584537

相关文章

  • 题解:CF1968G2 Division + LCP (hard version)
    https://www.luogu.com.cn/problem/CF1968G2CF1968G2Division+LCP(hardversion)题解前言这题可以\(O(n\sqrt{n}\logn)\)再各种优化做,算法是二分、哈希(不知道包不包含根号分治,但是有用到根号分治的思想)。如果读题解有些抽象的话可以看代码辅助理解。题意转化由于......
  • 题解:P10217 [省选联考 2024] 季风
    P10217[省选联考2024]季风题解题目传送门。初步化简题目注:本篇题解的所有下标均从\(1\)开始。设\(sumx_h\)表示\(\sum_{i=1}^{h}{x_i}\),\(sumy_i\)表示\(\sum_{i=1}^{h}{y_i}\)。于是题目给出的三个公式可以转化为:\((\sum_{i=1}^{m}{x_{i}^{′}})+sumx_{[(m-1......
  • 题解:AT_abc282_h [ABC282Ex] Min + Sum
    [ABC282Ex]Min+Sum题解题面传送门。题目要求有多少对\((l,r)\)满足\(1\lel\ler\len\)且\(\sum_{i=l}^{r}{b_i}+\min_{i=l}^{r}{a_i}\leS\)。考虑CDQ分治,那么我们需要不断寻找有多少对\((l,r)\)满足\(L\lel\leM<r\leR\)且\(\sum_{i=l}^{r}{b......
  • 【Mysql 数据库 undo log 文件无限膨胀,性能下降问题解决方案】
    数据库undolog文件无限膨胀,性能下降问题解决方案1.问题描述在Mysql数据目录中发现有个undo文件非常大,并且持续增长并且Historylistlength非常大------------TRANSACTIONS------------Trxidcounter3569860310Purgedonefortrx'sn:o<3185146100......
  • CentOS7 yum 安装 提示 网络问题解决办法
    1.sudovi/etc/yum.repos.d/CentOS-Base.repo2.将里边文件替换(insert%d  清除所有内容)  [base]name=CentOS-$releasever-Base-Aliyunbaseurl=http://mirrors.aliyun.com/centos/$releasever/os/$basearch/gpgcheck=1gpgkey=http://mirrors.aliyun.com/centos/RP......
  • 牛客周赛 Round 70题解
    牛客周赛Round70题解A小苯晨跑#include<bits/stdc++.h>usingnamespacestd;voidsolve(){inta[4];for(inti=0;i<4;i++)cin>>a[i];sort(a,a+4);if(a[0]==a[3]){cout<<"NO\n";}els......
  • 宇视网络摄像机IPC通过国标28181协议,无法接入国产系统部署的视频接入汇聚平台的问题解
    目录一.客户问题具体描述二.问题解决过程2.1网络排查2.2检查摄像机本身设置三.问题排查结果3.1平台查看设备是否在线3.2设置相关观看权限3.2.1新增并设置相关资源组3.2.2设置需要观看视频的角色3.2.3设置客户端登录用户3.3最终观看结果四.补充知识4.1ping的相关知......
  • 题解:P11217 【MX-S4-T1】「yyOI R2」youyou 的垃圾桶
    链接https://www.luogu.com.cn/problem/P11217分析先不考虑维护垃圾桶的攻击力,假设我们已经知道了所有垃圾桶的攻击力。翻倍操作可以用左移(<<)实现。首先先计算出所有垃圾桶的伤害值,然后看看能抗几个整轮。然后考虑不能抗的情况。由于所有垃圾桶的攻击力都为正数,所以可以二......
  • centos7软件仓库停用问题解决
    首先这只是一种临时解决方案,centos7已经停止维护了,软件仓库2024年7月已经停了,不建议使用了,建议切换到rockyos9,rockyos9里面包管理工具是dnf,dnf目前是兼容yum命令的,升级rockos除了软件数据的迁移,使用习惯几乎完全一样。解决方案如下:#打开仓库文件目录cd/etc/yum.repos.d#......
  • P1746 离开中山路 JAVA题解 (广搜和双向广搜优化)
    题目背景《爱与愁的故事第三弹·shopping》最终章。题目描述爱与愁大神买完东西后,打算坐车离开中山路。现在爱与愁大神在 x1,y1x1​,y1​ 处,车站在 x2,y2x2​,y2​ 处。现在给出一个 n×n(n≤1000)n×n(n≤1000) 的地图,00 表示马路,11 表示店铺(不能从店铺穿过),爱与愁......