\(\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. web.xml文件配置模板

    直接贴完整代码,当然,spring的核心控制器依赖包需要通过mean提前配置 <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.// ...

  2. 使用 try-catch

    ECMA-262 第 3 版引入了 try-catch 语旬,当 try-catch 语句中发生错误时, 浏览器会认为错误已经被处理了 ,因而不会报告错误.对于那些不要求用户懂技术,也不需要用户理解错 ...

  3. Linux上天之路(八)之用户和组

    主要内容. 用户创建,删除,修改 密码及密码文件 组创建,删除,修改 组密码及组配置文件 相关文件 Linux用户分类 超级管理员: UID为0 root用户拥有至高无上的命令,root用户不能改名 ...

  4. Python爬取中国知网文献、参考文献、引证文献

    前两天老师派了个活,让下载知网上根据高级搜索得到的来源文献的参考文献及引证文献数据,网上找了一些相关博客,感觉都不太合适,因此特此记录,希望对需要的人有帮助. 切入正题,先说这次需求,高级搜索,根据中 ...

  5. Jsp页面中常见的page指令

    注:图片如果损坏,点击文章链接:https://www.toutiao.com/i6513327323628962312/ 1.<JSP页面实际上就是Servlet> 2.<JSP页 ...

  6. for循环题目记录

    1.求1000以内的完数 /** * 一个数如果恰好等于它的因子之和,这个数就是完数,找出1000内的所有完数 * @author 努力Coding * @version * @data */ pub ...

  7. 纯手画WinForm的Alert提示弹出框

    纯手画WinForm的Alert弹框 一.窗体设置 设置以下属性: 属性名 属性值 说明 AutoScaleMode None 确定屏幕分辨率或字体更改时窗体如何缩放 BackColor 103, 1 ...

  8. 【PTA】5-1 输入一个正整数n,再输入n个学生的姓名和百分制成绩,将其转换为两级制成绩后输出。

    5-1 输入一个正整数n,再输入n个学生的姓名和百分制成绩,将其转换为两级制成绩后输出.要求定义和调用函数set_grade(stu, n),其功能是根据结构数组stu中存放的学生的百分制成绩scor ...

  9. RichTextBox单独设置文字颜色

    richTextBox1.Select(index, "str1".Length); richTextBox1.SelectionColor = Color.Red;

  10. 雷柏鼠标vt350Q配对

    vt350q 闲鱼捡了个垃圾vt350q,23元,无接收器,不知道好坏 鼠标线 拿到手插上线没法用,后来用了罗技anywhere2s的线可以,原来usb鼠标线是五根. 鼠标毛病 使用后发现滚轮有时候乱 ...