2019 Multi-University Training Contest 2 - 1009 - 回文自动机
http://acm.hdu.edu.cn/showproblem.php?pid=6599
有好几种实现方式,首先都是用回文自动机统计好回文串的个数。
记得把每个节点的cnt加到他的fail上,因为他既然出现了那么他的fail也当然会出现。
这里需要一直从fail向上找到一个长度恰好一半的节点,这也是TLE的来源,重复跳了大量的指针。dalao给了一种实现。
额外维护一个x数组,假如x[i]==0,说明还没人动过它,x[i]=i。
然后沿着fail把x[i]向上移动到第一个>=它的长度的一半的fail祖先,验证是不是长度恰好一半。
最后把i的fail父亲的x指针指向x[i],也就是把它的fail父亲直接x指向i的fail祖先,这样它父亲就不需要经过一系列没有用的fail转移了。
这个是个“不那么彻底的”路径压缩。源于一个点s的fail父f,f需要用的fail祖先必定是s的祖先,s可以每次把它父亲f一起给移动了。
当然也有hash大法、manacher大法。
hash大法好!
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
struct Node {
int len, ch[26], fail;
ll cnt, x, y;
//string str;
Node(int len = 0) : len(len), fail(0) {
memset(ch, 0, sizeof(ch));
//下面是维护额外信息
cnt = 0;
x = 0;
y = 0;
//str = "";
}
/*void show() {
printf(" str=\"%s\"\n", str.c_str());
printf(" len=%d cnt=%d\n", len, cnt);
}*/
};
const int MAXN = 300000;
ll ans2[MAXN + 5];
//PalindromicAutomaton
struct PAM {
Node nd[MAXN + 5];
int len, top, last; // len为字符串长度mtop为节点个数,last为最后插入字符所对应的节点
char s[MAXN + 5];
//string ls; //用来展示的辅助字符串
int getfail(int x) { //沿着fail指针找到第一个回文后缀
while(s[len - nd[x].len - 1] != s[len])
x = nd[x].fail;
return x;
}
void init() {
len = 0, top = 0, last = 0;
nd[top] = Node(0);
nd[top].fail = 1;
nd[++top] = Node(-1);
nd[top].fail = 0;
s[0] = '$';
}
void extend(char c) {
s[++len] = c;
int now = getfail(last); //找到插入的位置
//ls = nd[now].str + c; //用来展示的辅助字符串
if(!nd[now].ch[c - 'a']) { //若没有这个节点,则新建并求出它的fail指针
nd[++top] = Node(nd[now].len + 2);
nd[top].fail = nd[getfail(nd[now].fail)].ch[c - 'a'];
nd[now].ch[c - 'a'] = top;
}
last = nd[now].ch[c - 'a'];
//nd[last].str = ls; //用来展示的辅助字符串
//下面是维护额外信息
++nd[last].cnt;
}
/*void show() {
for(int i = top; i >= 0; --i) {
printf("node: id=%d\n", i);
nd[i].show();
printf("fail: id=%d\n", nd[i].fail);
nd[nd[i].fail].show();
puts("");
}
}*/
void count() {
for(int i = top; i >= 2; --i)
nd[nd[i].fail].cnt += nd[i].cnt;
}
void solve() {
for(int i = top; i >= 2; --i) {
if(nd[i].x == 0)
nd[i].x = i;
while(nd[nd[i].x].len > (nd[i].len + 1) / 2 )
nd[i].x = nd[nd[i].x].fail;
if(nd[nd[i].x].len == (nd[i].len + 1) / 2)
nd[i].y = 1;
nd[nd[i].fail].x = nd[i].x;
}
}
void ans(int n) {
memset(ans2, 0, sizeof(ans2[1]) * (n + 1));
for(int i = top; i >= 2; --i) {
ans2[nd[i].len] += nd[i].cnt * nd[i].y;
}
for(int i = 1; i <= n; ++i) {
printf("%lld%c", ans2[i], " \n"[i == n]);
}
}
} pam;
char s[MAXN + 5];
int main() {
#ifdef Yinku
freopen("Yinku.in", "r", stdin);
#endif // Yinku
while(~scanf("%s", s)) {
int n = strlen(s);
pam.init();
for(int i = 0; s[i] != '\0'; ++i)
pam.extend(s[i]);
//pam.show();
pam.count();
pam.solve();
pam.ans(n);
}
return 0;
}
2019 Multi-University Training Contest 2 - 1009 - 回文自动机的更多相关文章
- 2019 Multi-University Training Contest 2 I.I Love Palindrome String(回文自动机+字符串hash)
Problem Description You are given a string S=s1s2..s|S| containing only lowercase English letters. F ...
- 2019牛客暑期多校训练营(第六场)C - Palindrome Mouse (回文自动机)
https://ac.nowcoder.com/acm/contest/886/C 题意: 给出一个串A , 集合S里面为A串的回文字串 , 现在在集合S里面找出多少对(a,b),b为a的字串 分析: ...
- [2019杭电多校第二场][hdu6599]I Love Palindrome String(回文自动机&&hash)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6599 题目大意为求字符串S有多少个子串S[l,r]满足回文串的定义,并且S[l,(l+r)/2]也满足 ...
- hdu多校第二场1009 (hdu6599) I Love Palindrome String 回文自动机/字符串hash
题意: 找出这样的回文子串的个数:它本身是一个回文串,它的前一半也是一个回文串 输出格式要求输出l个数字,分别代表长度为1~l的这样的回文串的个数 题解: (回文自动机和回文树是一个东西) 首先用回文 ...
- URAL 2040 Palindromes and Super Abilities 2 (回文自动机)
Palindromes and Super Abilities 2 题目链接: http://acm.hust.edu.cn/vjudge/contest/126823#problem/E Descr ...
- URAL 2040 (回文自动机)
Problem Palindromes and Super Abilities 2 (URAL2040) 题目大意 给一个字符串,从左到右依次添加,询问每添加一个字符,新增加的回文串数量. 解题分析 ...
- 后缀自动机/回文自动机/AC自动机/序列自动机----各种自动机(自冻鸡) 题目泛做
题目1 BZOJ 3676 APIO2014 回文串 算法讨论: cnt表示回文自动机上每个结点回文串出现的次数.这是回文自动机的定义考查题. #include <cstdlib> #in ...
- [模板] 回文树/回文自动机 && BZOJ3676:[Apio2014]回文串
回文树/回文自动机 放链接: 回文树或者回文自动机,及相关例题 - F.W.Nietzsche - 博客园 状态数的线性证明 并没有看懂上面的证明,所以自己脑补了一个... 引理: 每一个回文串都是字 ...
- BZOJ2160拉拉队排练——回文自动机
题目描述 艾利斯顿商学院篮球队要参加一年一度的市篮球比赛了.拉拉队是篮球比赛的一个看点,好的拉拉队往往能帮助球队增加士气,赢得最终的比赛.所以作为拉拉队队长的楚雨荨同学知道,帮助篮球队训练好拉拉队有多 ...
随机推荐
- vue单页面项目中解决安卓4.4版本不兼容的问题
1.cnpm安装 cnpm i babel-polyfill --save cnpm i es6-promise --save 2.main.js引入 import ‘babel-polyfill‘ ...
- 快速幂(Fast Pow)
定义 快速求a^b%c的算法 原理 指数可以被二进制分解 那么a^b可以分解为a^2^k1*a^2^k2*…… 又显然a^2^(k+1)=a^(2^k*2)=(a^2^k)^2 所以可以将指数在二进制 ...
- 【LuoguP4770】[NOI2018] 你的名字
题目链接 题意简述 给定一个串 \(S\) 多组询问 , 每次给定一个串 \(T\) 和一个 区间 \([l,r]\) 求串\(T\) 有多少个本质不同的子串 满足不是 \(S[l...r]\) 的子 ...
- window 连接服务器工具
Xshell xftp 下载网址 以上两个软件均免费, 只需要邮件激活即可. 其中 xshell 主要用来连接服务器,方便使用命令行.xftp 方便传输文件.
- Windows Server 2003 IIS 使用 Excel.Application
在Server2003服务器系统中,配置ASP调用CreateObject("Excel.Application")对象 1.先在服务器中安装Microsoft Excel 2.打 ...
- http协议的深刻理解
https://www.cnblogs.com/mayite/p/9095986.html
- Spark Streaming的优化之路—从Receiver到Direct模式
作者:个推数据研发工程师 学长 1 业务背景 随着大数据的快速发展,业务场景越来越复杂,离线式的批处理框架MapReduce已经不能满足业务,大量的场景需要实时的数据处理结果来进行分析.决 ...
- 大数据笔记(二十一)——NoSQL数据库之Redis
一.Redis内存数据库 一个key-value存储系统,支持存储的value包括string(字符串).list(链表).set(集合).zset(sorted set--有序集合)和hash(哈希 ...
- 【zabbix】zabbix 高可用架构的实现
https://www.jianshu.com/p/249d47b089b4?utm_campaign=maleskine&utm_content=note&utm_medium=se ...
- ReentrantLock 源码分析
ReentrantLock 1)ReentrantLock 类实现了和 synchronized 一样的内存语义,同时该类提供了更加灵活多样的可重入互斥锁定操作. 2)ReentrantLock 实例 ...