\(\mathcal{Description}\)

  Link.

  给定字符串 \(s\),处理 \(q\) 次操作:

  1. 在 \(s\) 前添加字符串;
  2. 在 \(s\) 后添加字符串;
  3. 求 \(s\) 的所有非空回文子串数目。

  任意时刻 \(|s|\le4\times10^5\),\(q\le10^5\)。

\(\mathcal{Solution}\)

  双向 PAM 模板题。

  思考一个正常的 PAM 所维护的——一个 DFA,每个结点的连边代表左右各加同一个字符;还有一个 fail 树,连向结点的最长回文后缀(当然也就是最长回文前缀)。在双向 PAM 也是一个道理,增量法构造过程中顺便处理 fail 树深度和即可。

  复杂度 \(\mathcal O(|s|+q)\)。

\(\mathcal{Solution}\)

/*~Rainybunny~*/

#include <cstdio>
#include <cstring> #define rep( i, l, r ) for ( int i = l, rep##i = r; i <= rep##i; ++i )
#define per( i, r, l ) for ( int i = r, per##i = l; i >= per##i; --i ) typedef long long LL; const int MAXN = 4e5, MAXL = 7e5;
char s[MAXL + 10];
int ptrf, ptrb; struct PalindromeAutomaton {
int node, len[MAXN + 5], fail[MAXN + 5], ch[MAXN + 5][26];
int rlas, llas, dep[MAXN + 5]; PalindromeAutomaton() { node = rlas = llas = 1, len[1] = -1, fail[0] = 1; } inline int pushF( char c ) {
s[--ptrf] = c, c -= 'a'; int p = llas;
for ( ; s[ptrf + len[p] + 1] != s[ptrf]; p = fail[p] );
if ( !ch[p][c] ) {
len[++node] = len[p] + 2; int q = fail[p];
for ( ; s[ptrf + len[q] + 1] != s[ptrf]; q = fail[q] );
dep[node] = dep[fail[node] = ch[q][c]] + 1, ch[p][c] = node;
}
llas = ch[p][c];
if ( len[llas] == ptrb - ptrf + 1 ) rlas = llas;
return dep[llas];
} inline int pushB( char c ) {
s[++ptrb] = c, c -= 'a'; int p = rlas;
for ( ; s[ptrb - len[p] - 1] != s[ptrb]; p = fail[p] );
if ( !ch[p][c] ) {
len[++node] = len[p] + 2; int q = fail[p];
for ( ; s[ptrb - len[q] - 1] != s[ptrb]; q = fail[q] );
dep[node] = dep[fail[node] = ch[q][c]] + 1, ch[p][c] = node;
}
rlas = ch[p][c];
if ( len[rlas] == ptrb - ptrf + 1 ) llas = rlas;
return dep[rlas];
}
} pam; int main() {
ptrf = ( ptrb = 3e5 ) + 1;
LL ans = 0;
for ( char c; 'a' <= ( c = getchar() ) && c <= 'z';
ans += pam.pushB( c ) ); int q, op; char tmp[1005];
for ( scanf( "%d", &q ); q--; ) {
scanf( "%d", &op );
if ( op == 1 ) {
scanf( "%s", tmp );
for ( int i = 0; tmp[i]; ans += pam.pushB( tmp[i++] ) );
} else if ( op == 2 ) {
scanf( "%s", tmp );
for ( int i = 0; tmp[i]; ans += pam.pushF( tmp[i++] ) );
} else {
printf( "%lld\n", ans );
}
} return 0;
}

Solution -「LOJ #141」回文子串 ||「模板」双向 PAM的更多相关文章

  1. 图解最长回文子串「Manacher 算法」,基础思路感性上的解析

    问题描述: 给你一个字符串 s,找到 s 中最长的回文子串. 链接:https://leetcode-cn.com/problems/longest-palindromic-substring 「Ma ...

  2. hdu 3068 最长回文 【Manacher求最长回文子串,模板题】

    欢迎关注__Xiong的博客: http://blog.csdn.net/acmore_xiong?viewmode=list 最长回文                                 ...

  3. hdu 3068 最长回文子串 马拉车模板

    前几天用后缀数组写过一次这题,毫无疑问很感人的TLE了-_-|| 今天偶然发现了马拉车模板,O(N)时间就搞定 reference:http://acm.uestc.edu.cn/bbs/read.p ...

  4. manacher求最长回文子串算法模板

    #include <iostream> #include <cstring> #include <cstdlib> #include <stdio.h> ...

  5. 最长回文子串 —— Manacher (马拉车) 算法

    最长回文子串 回文串就是原串和反转字符串相同的字符串.比如 aba,acca.前一个是奇数长度的回文串,后一个是偶数长度的回文串. 最长回文子串就是一个字符串的所有子串中,是回文串且长度最长的子串. ...

  6. Manacher (马拉车) 算法:解决最长回文子串的利器

    最长回文子串 回文串就是原串和反转字符串相同的字符串.比如 aba,acca.前一个是奇数长度的回文串,后一个是偶数长度的回文串. 最长回文子串就是一个字符串的所有子串中,是回文串且长度最长的子串. ...

  7. LeetCode 5——最长回文子串

    1. 题目 2. 解答 我们定义状态 state[i][j] 表示子串 s[i, j] 是否为回文子串,如果 s[i, j] 为回文子串,并且有 s[i-1] == s[j+1],那么 s[i-1, ...

  8. 每日一道 LeetCode (48):最长回文子串

    每天 3 分钟,走上算法的逆袭之路. 前文合集 每日一道 LeetCode 前文合集 代码仓库 GitHub: https://github.com/meteor1993/LeetCode Gitee ...

  9. LeetCode[5] 最长的回文子串

    题目描述 Given a string S, find the longest palindromic substring in S. You may assume that the maximum ...

随机推荐

  1. gitlab新增ssh

    https://blog.csdn.net/u011925641/article/details/79897517

  2. Go语言中各种数据格式转换

    Go语言各种数据类型格式转换 package main import ( "encoding/json" "fmt" "reflect" & ...

  3. Centos6.9虚拟机环境搭建

    原文链接:https://www.toutiao.com/i6481534700216123918/ 一.准备工具 VMware Workstation CentOS-6.9-x86_64-minim ...

  4. Win10编辑Host文件授权问题

    今天重温Kafka命令, 使用KafkaTool连接Broker,需要修改主机名,发现host修改时,提示以下错误: C:\Windows\System32\drivers\etc\hosts.txt ...

  5. 2018HPU暑期集训第四次积分训练赛 K - 方框 题解(图形打印)

    思路分析:题目已经明确透露了这道题的解法:就是画框.当 输入的边长  的话,就表示可以在内层继续嵌套一个方框.废话就不多说了,直接上代码吧! 代码如下: #include <iostream&g ...

  6. Android官方文档翻译 四 1.2Running Your App

    Running Your App If you followed the previous lesson to create an Android project, it includes a def ...

  7. 使用Cesium Stories在3D Tilesets中检查Features

    Cesium中文网:http://cesiumcn.org/ | 国内快速访问:http://cesium.coinidea.com/ 我们创建了3D Tiles用以流式化.可视化和分析大量的三维内容 ...

  8. Elasticsearch使用系列-ES简介和环境搭建

    一.简介 Elasticsearch是一个基于Lucene的搜索服务器.它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口.Elasticsearch是用Java语言开发的,并 ...

  9. 513. Find Bottom Left Tree Value

    Given a binary tree, find the leftmost value in the last row of the tree. Example 1: Input: 2 / \ 1 ...

  10. Superset SSO改造和自定义宏命令

    目录 背景 关于Superset 需要解决的问题 定制化改造 准备环境 改造OAuth SSO 安装依赖 配置SSO 添加自定义的SecurityManager 运行一下吧 自定义宏命令 开启配置 添 ...