2019牛客暑期多校训练营(第四场)I string(后缀数组 + 回文树)

Docker一键部署Synopsys EDA全家桶(VCS/Verdi 2018版)保姆级教程 本文提供了一份详尽的Docker容器化部署Synopsys EDA工具链(VCS/Verdi 2018版)的保姆级教程。通过环境隔离与标准化,解决传统安装的依赖冲突问题,并重点攻克了容器内GUI图形界面显示的核心难题。教程涵盖从Docker基础安装、镜像获取、容器启动配置,到使用X11转发或VNC实现Verdi完美显示的完整实践,旨在帮助芯片设计工程师快速构建稳定、可移植的一键化EDA工作环境。 阅读详情

题目链接
题解:
如果求出 字符串中不同的子串数量 和 反转后的字符串中不同子串的数量,那么两种的字符串合在一起之后的不同的字符串数量再 / 2 就是答案。
但是如果原来的字符串是回文串的话,那么回文串本来应该要计算两次的,但是发现它只计算了一次,所以要加上回文串的数量再 / 2。
具体做法,求不同子串的数量可以用后缀数组,先将原字符串反转加在后面,中间用一个其他字符隔开。回文子串个数可以用回文树。
代码:

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
#define PI acos(-1.0)
#define INF 0x3f3f3f3f3f3f3f3f
#define P pair<ll, int>
#define debug(x) cout << #x << ": " << x << " "
#define fastio ios::sync_with_stdio(false), cin.tie(0)
const int mod = 1e9 + 7;
const int M = 1000000 + 10;
const int N = 400000 + 10;

ll n, rk[N];
ll k, tmp[N];
bool compare_sa(int i,int j){
    if(rk[i]!=rk[j]) return rk[i]<rk[j];
    else{
        int x=i+k<=n?rk[i+k]:-1;
        int y=j+k<=n?rk[j+k]:-1;
        return x<y;
    }
}
void calc_sa(string s,int *sa){
    for(int i=0;i<=n;i++){
        sa[i]=i;
        rk[i]=i<n?s[i]:-1;
    }
    for(k=1;k<=n;k*=2){
        sort(sa,sa+n+1,compare_sa);
        tmp[sa[0]]=0;
        for(int i=1;i<=n;i++){
            tmp[sa[i]]=tmp[sa[i-1]]+(compare_sa(sa[i-1],sa[i])?1:0);
        }
        for(int i=0;i<=n;i++){
            rk[i]=tmp[i];
        }
    }
}
void calc_lcp(string s,int *sa,int *lcp){
    for(int i=0;i<=n;i++) rk[sa[i]]=i;
    int h=0;
    lcp[0]=0;
    for(int i=0;i<n;i++){
        int j=sa[rk[i]-1];
        if(h>0) h--;
        for(;j+h<n&&i+h<n;h++){
            if(s[j+h]!=s[i+h]) break;
        }
        lcp[rk[i]-1]=h;
    }
}

const int MAX = 200000 + 10;
const int ALP = 26;
struct Palindromic_Tree {
    int son[MAX][ALP]; //转移边
    int fail[MAX]; //fail 指针
    int cnt[MAX]; //当前节点表示的回文串在原串中出现了多少次
    int num[MAX]; //当前节点 fail 可以向前跳多少次
    int len[MAX]; //当前节点表示的回文串的长度
    int S[MAX]; //插入的字符串
    int last; //最后一次访问到的节点,类似 SAM
    int n; //插入的字符串长度
    int p; //自动机的总状态数

    int newnode(int l) {
        memset(son[p], 0, sizeof(son[p]));
        cnt[p] =  num[p] = 0;
        len[p] = l;
        return p++;
    }

    void init() {
        p = 0;
        newnode(0);
        newnode(-1);
        last = n = 0;
        S[n] = -1;
        fail[0] = 1;
    }

    int get_fail(int x) {
        while (S[n - len[x] - 1] != S[n]) x = fail[x];
        return x;
    }

    void add(int c) {
        c -= 'a';
        S[++n] = c;
        int cur = get_fail(last); //通过上一次访问的位置去扩展
        if (!son[cur][c]) { //如果没有对应的节点添加一个新节点
            int now = newnode(len[cur] + 2);
            fail[now] = son[get_fail(fail[cur])][c]; //通过当前节点的 fail 去扩展出新的 fail
            son[cur][c] = now;
            num[now] = num[fail[now]] + 1; //记录 fail 跳多少次
        }
        last = son[cur][c];
        cnt[last]++; //表示当前节点访问了一次
    }
    void count() {
        //如果某个节点出现一次,那么他的 fail 也一定会出现一次,并且在插入的时候没有计数
        for (int i = p - 1; i >= 0; i--) cnt[fail[i]] += cnt[i];
    }
} AUT;

string s;
int sa[N], height[N];

signed main()
{
    cin >> s;
    ll len = n = s.length();

    string st = s; reverse(s.begin(), s.end()); s = st + '#' + s;
    n = 2 * n + 1; calc_sa(s, sa), calc_lcp(s, sa, height);
    ll p = 0;
    for(int i = 1; i < n; i ++) p += height[i];
    p = n * (n + 1) / 2 - (len + 1) * (len + 1) - p;

    AUT.init();
    for(int i = 0; i < len; i ++) AUT.add(s[i]);
    ll q = AUT.p - 2;

    cout << (p + q) / 2 << endl;

    return 0;
}

/*

  Rejoicing in hope, patient in tribulation.

*/

ParaView: 从 2 或 3 个标量创建向量 阅读详情

相关推荐

QCM6490平台DDR测试:从QDUTT配置到眼图分析的实战指南

本文详细介绍了QCM6490平台DDR测试的全流程,从QDUTT工具安装配置到眼图分析,提供了实战操作指南和常见问题解决方案。通过具体案例分享,帮助工程师掌握DDR测试技巧,确保内存稳定性,特别适用于物联网和边缘计算设备的开发调试。

weixin_33910191的博客 456

2020牛客暑期多校训练营(第二场)(A hash 计数 +kmp next数组 去重)

题目链接 All with Pairs 正在上传…重新上传取消

ccsu_deer 1993

Java实战:绿盾加密文件批量解密工具Ldterm的实现与优化

本文详细介绍了基于Java开发的绿盾加密文件批量解密工具Ldterm的实现与优化过程。通过分析绿盾加密机制,结合Java流处理能力,实现了高效的文件解密方案,并分享了多线程处理、内存优化等性能提升技巧,适用于企业级数据迁移与备份场景。

weixin_29314405的博客 488

2019牛客暑期多校训练营(第四场)I string —— 后缀自动机+回文自动机

This way 题意: 给你一个串,任意两个字符串被视为重复的当且仅当这两个字符串相同或者这个字符串与另一个字符串的逆序相同。问你最多能找出多少不相同的子串。 题解: 情况大致可分为出现一次和出现两次及以上的情况。 那么我们对于求解这种问题考虑后缀自动机。 首先我们需要知道哪些是翻转过后依然存在的,那么我们需要在后缀自动机里加入原串和翻转后的串。但是这时候会出现一个问题:aa…aab这样的串,与...

天翼之城的博客 270

基于STM32L4XX、HAL库的TESEO-LIV4FTR定位模块驱动程序设计

支持多星座系统:GPS、GLONASS、Galileo和北斗。支持NMEA 0183协议和ST专有协议。高灵敏度:-167dBm跟踪灵敏度。低功耗设计,适合物联网和便携设备。内置LNA和SAW滤波器。

zhusl6688的博客 237

定位教程7---旋转中心标定之方法二

手算相机相对机器人关系

Quintin 6230

2019牛客第四场I题 string

链接:https://ac.nowcoder.com/acm/contest/884/I 题意:求string串有多少个本质不同的子串,且这些子串之间两两不存在 a==rev(a),即不存在长度1以上的回文串 题解: 要算string 和 rev(string)的所有子串,对string 和rev(string)建立广义后缀自动机,则理论上所有子串增加了一倍,但实际回文串和 不是回文...

qq_41818544的博客 909

基于方差分解分析气象/水文干旱驱动因素(含MATLAB全代码)

简介基于方差分解方法分析气象/水文干旱驱动因素

WW、forever的博客 801

POJ 2752 (字符串中找即是前缀又是后缀的子串)

Seek the Name, Seek the Fame Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 24200 Accepted: 12618 Description The little cat is so famous, that many couples tramp over hill...

越看越喜欢啊 1465

【2026华为OD新规机考】最新套题持续更新【完全原创题解 | 详细考点分类 | 不断更新题目 | 六种主流语言Py+Java+Cpp+C+Js+Go】

可上练习华子OD、大厂真题绿色聊天软件戳od1441了解算法冲刺训练(备注【优快云】否则不通过)

weixin_48157259的博客 505

Superpowers与 OpenSpec、Spec Kit 对比

按照官方仓库定义,Superpowers 是一套构建在 composable skills 之上的完整软件开发工作流。它不是单纯的 prompt 集合,而是把一系列工程动作做成默认流程。一个需要明确的点:Superpowers 并不只偏 Claude Code,根据。

人不风流枉少年 1812

2019牛客暑期多校训练营(第四场)----I- string

首先发出题目链接: 链接:https://ac.nowcoder.com/acm/contest/884/I 来源:牛客网 涉及:广义后缀自动机,后缀数组,manache,回文树 点击这里回到2019牛客暑期多校训练营解题—目录贴 题目如下: 代码如下 #include <iostream> #include <string> #include <algorithm> using namespace std; typedef long long ll; const

weixin_43702895的博客 271

【网络基础2】路由器的 “两扇门”:二层接口和三层接口到底有啥不一样?

家里的路由器背后总有几个网线接口,有的标着 “LAN”,有的标着 “WAN”;公司机房的路由器上,接口更是五花八门,有的插着网线,有的连着光纤,旁边还贴着 “GE0/0/1”“Eth-Trunk1” 这样的标签。你可能会想:不就是插网线的地方吗?有啥区别?其实,这些接口分 “二层接口” 和 “三层接口”,它们的作用差得远了 —— 就像你家的门,有的是 “小区内的单元门”(只通小区内部),有的是 “小区的大门”(能通往外面的世界)。接下来,咱们用大白话 + 生活例子,一点点把这两种接口讲透。

jundao1997的专栏 563

2019牛客暑期多校训练营(第七场)A.String

2019牛客暑期多校训练营(第七场)A.String 题目链接 题目描述 A string is perfect if it has the smallest lexicographical ordering among its cyclic rotations. For example: “0101” is perfect as it is the smallest string among (“0101”, “1010”, “0101”, “1010”). Given a 01 string, you

旺崽的博客 2594

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

2019牛客暑期多校训练营(第四场)I - String (后缀自动机+回文树)

题目链接 题意 给一个字符串,求字符串子串的最大集合,集合中字符串互不相等,相等的定义为:a≠ba =\not ba≠​b 而且 a≠rev(b)a =\not rev(b)a≠​rev(b) 例如字符串abacabacabac,最大不相等集合 {abac,b,a,ab,aba,bac,ac,c}\{ abac,b,a,ab,aba,bac,ac,c\}{abac,b,a,ab,aba,b...

Running Bit. 629

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

2019牛客暑期多校训练营(第四场)

A - meeting 题意: 在一棵树上,多个节点有人。选择一个节点使得这些人到这个点的路径最大值最小。 解析: 将不存在人的叶子都割掉,知道所有叶子都是人为止,你会发现就是求剩下来树的直径。 代码: #include<bits/stdc++.h> using namespace std; const int N=1e5+5; struct node { int to,nex...

QAQ 1239

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

2019牛客暑期多校训练营(第三场)B.Crazy Binary String

2019牛客暑期多校训练营(第三场)B.Crazy Binary String 题目链接 题目描述 ZYB loves binary strings (strings that only contains ‘0’ and ‘1’). And he loves \textit{equal binary strings}equal binary strings more, where the number of ‘0’ and the number of ‘1’ in the string are equal.

旺崽的博客 2696

题解 | string-2019牛客暑期多校训练营第四场I题

题目来源于牛客竞赛:https://ac.nowcoder.com/acm/contest/discuss 题目描述: 输入描述: 输出描述: 示例1: 题解: 代码: #include <bits/stdc++.h> using namespace std; typedef long long ll; #define SZ 455555 char s[SZ]; int n;...

lastbye的博客 231

2019牛客暑期多校训练营(第四场) I-string 广义后缀自动机+回文自动机

题意 分析 考虑两个串如果反过来不相同个数怎么统计 其实就是正串和反串都放在一个广义后缀自动机上统计,然后 答案/2 这样对吗?我们考虑自己本身回文的情况,还要加上本质不同的回文串个数 直接上回文自动机就可以了 代码 #include <bits/stdc++.h> using namespace std; typedef long long ll; const ll N = 800...

OIer,ACMer,专注于 c++/编译器/虚拟机/AI学习 320

2026牛客暑期多校训练营1

先分成size等于8的,然后对8奇偶分析,就可以了。

2603_96556175的博客 325

【2019牛客暑期多校训练营(第三场)】B-Crazy Binary String 题解

题目来自于:2019牛客暑期多校训练营(第三场)B-Crazy Binary String 题目大意: 输入的第一个数字n代表字符串的长度。然后求这个字符串子串中的最长二进制子串和字序列分别是多长。 分析: 这里子串用暴力的方法无法求出最优结果,时间也可能会超出,所以我们这里用空间换时间的的方法,而子序列只需要将0和1的数量取其中最小然后再除以二就可以了,因为序列可以是不连续的 贴上c++代码:...

Drmon.的博客 333

2020牛客暑期多校训练营(第四场)C Count New String —— 树形后缀自动机

This way 题意: 给你一个长度为n的串,定义 表示得到的串的第i位是输入串s中第x~x+i位的最大值。 问你 也就是所有子串做一次之后再做一次。有多少种本质不同的子串。 题解: 那么可以看出得到的串是单调递增的,所以其实这道题目就是问你每个后缀做一次f之后的所有子串中有多少种本质不同的子串。 在比赛的时候一直在写E,没有时间看着道题,但是估计看了也不一定能做出来,毕竟我还真没想到后缀自动机可以树形建树。 从后往前,对于当前点i,找到后面第一个值大于等于它的位置p,然后从那个地方增加长度为p-

天翼之城的博客 348

数据结构 - Classical String Problem - 2020牛客暑期多校训练营(第三场)

数据结构 - Classical String Problem - 2020牛客暑期多校训练营(第三场) 题意: 给定一个字符串S,以及Q组询问,给定一个字符串S,以及Q组询问,给定一个字符串S,以及Q组询问, 分成两种情况:分成两种情况:分成两种情况: A x:输出S的第x个字符。A\ x:输出S的第x个字符。A x:输出S的第x个字符。 Q x:若x>0,表示将S的长度为x前缀转移到S的尾部。Q\ x:若x>0,表示将S的长度为x前缀转移到S的尾部 。Q&nbs

njuptACMcxk的博客 177

2019牛客暑期多校训练营(第七场)A String

A string is perfect if it has the smallest lexicographical ordering among its cyclic rotations. For example: “0101” is perfect as it is the smallest string among (“0101”, “1010”, “0101”, “1010”). Give...

旺崽的博客 999

2019牛客暑期多校训练营(第四场) K numbers

链接:https://ac.nowcoder.com/acm/contest/884/K?&headNav=acm&headNav=acm 来源:牛客网 题目描述 300iq loves numbers who are multiple of 300. One day he got a string consisted of numbers. He wants to kn...

pxlsdz的博客 561

2019牛客暑期多校训练营(第四场)I-string(SAM+PAM)

LINK 题意 我们说串aaa和串bbb不等价是说a!=ba!=ba!=b且a!=rev(b)a!=rev(b)a!=rev(b) 其中rev(b)rev(b)rev(b)是bbb的反转串 从sss串中选出最多的子串,使得任意两个子串都不等价。 原问题相当于,某个子串和它的反串只能计算一次贡献 考虑把原串和反串拼起来变成s#rev(s)s\#rev(s)s#rev(s) 其中sss是原串,rev(s)rev(s)rev(s)是反串 sss的所有本质不同子串在sss中计算过了一遍 若某个子串的反串没在sss

jziwjxjd的博客 418
上一篇: CodeForces - 786B (线段树?优化建图最短路)
下一篇: 2019牛客暑期多校训练营(第三场)G Removing Stones (分治+RMQ)
ttoobne
博客等级 码龄9年 13粉丝 59原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值