杭电多校HDU 6599 I Love Palindrome String (回文树)题解
题意:
定义一个串为\(super\)回文串为:
\(\bullet\) 串s为主串str的一个子串,即\(s = str_lstr_{l + 1} \cdots str_r\)
\(\bullet\) 串s为回文串
\(\bullet\) 串\(str_lstr_{l + 1}...str_{\llcorner (l + r) / 2 \lrcorner}\)也是回文串
问长度为1、2、3 \(\cdots n\)的\(super\)回文串分别出现了几次
思路:
回文树建一下,然后每次新建一个节点的时候用hash快速判断一下是不是\(super\)回文串,然后回文树统计一下个数。
代码:
#include<map>
#include<set>
#include<cmath>
#include<cstdio>
#include<stack>
#include<ctime>
#include<vector>
#include<queue>
#include<cstring>
#include<string>
#include<sstream>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 3e5 + 5;
const int INF = 0x3f3f3f3f;
const ull seed = 131;
const ll MOD = 1e9 + 7;
using namespace std;
ull ha[maxn], fac[maxn];
int ans[maxn];
ull getstring(int l, int r){
return ha[r] - ha[l - 1] * fac[r - l + 1];
}
struct PAM{
int nex[maxn][26]; //指向的一个字符的节点
int fail[maxn]; //失配节点
int len[maxn]; //当前节点回文长度
int str[maxn]; //当前添加的字符串
int cnt[maxn]; //节点出现次数
int last;
int tot; //PAM中节点数
int N; //添加的串的个数
int satisfy[maxn];
int newnode(int L){
for(int i = 0; i < 26; i++) nex[tot][i] = 0;
len[tot] = L;
cnt[tot] = 0;
return tot++;
}
void init(){
tot = 0;
newnode(0);
newnode(-1);
last = 0;
N = 0;
str[0] = -1;
fail[0] = 1;
}
int getfail(int x){
while(str[N - len[x] - 1] != str[N]) x = fail[x];
return x;
}
void add(char ss){
int c = ss - 'a';
str[++N] = c;
int cur = getfail(last);
if(!nex[cur][c]){
int now = newnode(len[cur] + 2);
fail[now] = nex[getfail(fail[cur])][c];
nex[cur][c] = now;
int need = (len[now] + 1) / 2;
if(len[now] == 1 || getstring(N - len[now] + 1, N - len[now] + need) == getstring(N - need + 1, N)) satisfy[now] = 1;
else satisfy[now] = 0;
}
last = nex[cur][c];
cnt[last]++;
}
void count(){
for(int i = tot - 1; i >= 0; i--){
cnt[fail[i]] += cnt[i];
if(satisfy[i]) ans[len[i]] += cnt[i];
}
}
}pa;
char s[maxn];
int main(){
fac[0] = 1;
for(int i = 1; i < maxn; i++) fac[i] = fac[i - 1] * seed;
while(~scanf("%s", s + 1)){
pa.init();
int len = strlen(s + 1);
ha[0] = 1;
for(int i = 1; i <= len; i++){
ha[i] = ha[i - 1] * seed + s[i];
}
for(int i = 1; i <= len; i++) ans[i] = 0;
for(int i = 1; i <= len; i++){
pa.add(s[i]);
}
pa.count();
for(int i = 1; i <= len; i++){
if(i != 1) printf(" ");
printf("%d", ans[i]);
}
puts("");
}
return 0;
}
杭电多校HDU 6599 I Love Palindrome String (回文树)题解的更多相关文章
- HDU 6599 I Love Palindrome String (回文树+hash)
题意 找如下子串的个数: (l,r)是回文串,并且(l,(l+r)/2)也是回文串 思路 本来写了个回文树+dfs+hash,由于用了map所以T了 后来发现既然该子串和该子串的前半部分都是回文串,所 ...
- 杭电多校HDU 6579 Operation (线性基 区间最大)题解
题意: 强制在线,求\(LR\)区间最大子集异或和 思路: 求线性基的时候,记录一个\(pos[i]\)表示某个\(d[i]\)是在某个位置更新进入的.如果插入时\(d[i]\)的\(pos[i]\) ...
- HDU 5157 Harry and magic string(回文树)
Harry and magic string Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/O ...
- HDU.5394.Trie in Tina Town(回文树)
题目链接 \(Description\) 给定一棵\(Trie\).求\(Trie\)上所有回文串 长度乘以出现次数 的和.这里的回文串只能是从上到下的一条链. 节点数\(n\leq 2\times ...
- [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 6656 Kejin Player(概率DP)题解
题意: 最低等级\(level\ 1\),已知在\(level\ i\)操作一次需花费\(a_i\),有概率\(p_i\)升级到\(level\ i+1\),有\(1 - p_i\)掉级到\(x_i( ...
- 杭电多校HDU 6601 Keen On Everything But Triangle(主席树)题解
题意: 有\(n\)根长度不一的棍子,q次询问,求\([L,R]\)区间的棍子所能组成的周长最长的三角形.棍长\(\in [1, 1e9]\),n\(\in [1, 1e5]\). 思路: 由于不构成 ...
- 杭电多校HDU 6586 String(预处理 + 贪心)题解
题意: 给你一个串,现需要你给出一个子序列,满足26个约束条件,\(len(A_i) >= L_i\) 且 \(len(A_i) <= R_i\), \(A_i\)为从a到z的26个字母. ...
- [2019杭电多校第三场][hdu6609]Find the answer(线段树)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6609 大致题意是求出每个位置i最小需要将几个位置j变为0(j<i),使得$\sum_{j=1}^ ...
随机推荐
- Python入门之修改jupyter启动目录
[导读]在给大家分享知识的过程中,我们也会分享一些小技巧,能够帮助大家在学习过程中有更好的体验.之前我们给大家分享了anaconda安装教程以及jupyter notebook使用方法,今天我们为大家 ...
- Databricks 第9篇:Spark SQL 基础(数据类型、NULL语义)
Spark SQL 支持多种数据类型,并兼容Python.Scala等语言的数据类型. 一,Spark SQL支持的数据类型 整数系列: BYTE, TINYINT:表示1B的有符号整数 SHORT, ...
- httpd反向代理实践(一)
div.example { background-color: rgba(229, 236, 243, 1); color: rgba(0, 0, 0, 1); padding: 0.5em; mar ...
- Linux常用命令:文件操作命令
Linux系统命令主要包括文件操作.网络命令和性能命令,本文介绍常用文件操作命令. 修改文件属性 文件类型: 普通文件:- 目录文件:d 块设备文件:b,硬盘 字符设备: c,串行端口的接口设备,例如 ...
- JavaScript代码是怎么执行的?
前言 众所周知,JavaScript是单线程语言.所以JavaScript是按顺序执行的! 先编译再执行 变量提升 请看下面的例子: console.log(cat) catName("Ch ...
- 反射型XSS
反射型XSS漏洞详解 http://www.ttlsa.com/safe/xss-description/ 一.原理 如果一个应用程序使用动态页面向用户显示错误消息,就会造成一种常见的XSS漏洞.通常 ...
- 90% 的 Java 程序员都说不上来的为何 Java 代码越执行越快(1)- JIT编译优化
麻烦大家帮我投一票哈,谢谢 经常听到 Java 性能不如 C/C++ 的言论,也经常听说 Java 程序需要预热,那么其中主要原因是啥呢? 面试的时候谈到 JVM,也有很多面试官喜欢问,为啥 Java ...
- nginx常用功能和配置
nginx常用功能和配置 1.nginx常用功能和配置 1.1 限流 1.2 压力测试工具--Ab 1.2.1安装 1.2.2 测试 1.2.3 返回值 1.3 limit_conn_zone 1.4 ...
- typedef void (*sighandler_t)(int);
typedef void (*sighandler_t)(int); sighandler_t signal(int signum, sighandler_t handler); ---------- ...
- 调用ajax 跨域调用接口
//ajax 跨域请求数据 function ajaxType (){ $.ajax({ url: "http://127.0.0.1:9090/spring_mvc/HttpClient/ ...