HDU-6599 I Love Palindrome String(回文自动机+字符串hash)
题意:给定一个字符串\(|S|\le 3\times 10^5\)
对于每个 \(i\in [1,|S|]\) 求有多少子串\(s_ls_{l+1}\cdots s_r\)满足下面条件
- \(r-l+1 = i\)
- \(s_ls_{l+1}\cdots s_r\)是一个回文串
- \(s_ls_{l+1}\cdots s_{\lfloor(l+r)/2\rfloor}\)也是一个回文串
回文树学习:https://blog.csdn.net/Clove_unique/article/details/53750322
根据条件可知\(s_ls_{l+1}\cdots s_{\lfloor(l+r)/2\rfloor-1} == s_{\lfloor(l+r)/2\rfloor}\cdots s_r\)
先用回文自动机求出本质不同的回文串
- 第一种方法是回文树中创建新节点(意味着新的回文串)时判断该回文串是否满足上面条件,再建好树之后从后向前计算个数时累加即可
- 第二种是利用回文树中fail指针特性,每次循环找fail所指的回文串是否满足条件,直到根节点或找到为止,此次寻找结果可以更新到下一层fail指针所指的节点中(避免多次重复寻找,不然会T)
第一种方法代码:
#include <bits/stdc++.h>
using namespace std;
const int N = 3e5+10;
typedef unsigned long long ull;
typedef long long ll;
ull has[N],pn[N],base = 131;
ull getVal(int l,int r){
return has[r] - has[l-1] * pn[r-l+1];
}
ll res[N];
char s[N];
namespace PAT{
const int SZ = 6e5+10;
int ch[SZ][26],fail[SZ],cnt[SZ],len[SZ],tot,last,pos[SZ],satisfy[SZ];
void init(int n){
for(int i=0;i<=n+10;i++){
fail[i] = cnt[i] = len[i] = 0;
for(int j=0;j<26;j++)ch[i][j] = 0;
}
s[0] = -1;fail[0] = 1;last = 0;
len[0] = 0;len[1] = -1,tot = 1;
}
inline int newnode(int x){
len[++tot] = x;return tot;
}
inline int getfail(int x,int n){
while(s[n-len[x]-1] != s[n])x = fail[x];
return x;
}
void create(char *s,int n){
s[0] = -1;
for(int i=1;i<=n;++i){
int t = s[i]- 'a';
int p = getfail(last,i);
if(!ch[p][t]){
int q = newnode(len[p]+2);
fail[q] = ch[getfail(fail[p],i)][t];
ch[p][t] = q;
int need = (len[q] + 1) /2;
if(len[q] == 1 || getVal(i-len[q]+1,i-len[q] + need) == getVal(i-need +1,i))satisfy[q] = 1;
else satisfy[q] = 0;
}
++cnt[last = ch[p][t]];
}
}
void solve(){
for(int i=tot;i>=2;i--){
cnt[fail[i]] += cnt[i];
if(satisfy[i])res[len[i]] += cnt[i];
}
}
}
int main(){
pn[0] = 1;
for(int i=1;i<N;i++)pn[i] = pn[i-1] * base;
while(~scanf("%s",s+1)){
int n = strlen(s+1);
has[0] = 1;
for(int i=1;i<=n;i++){
has[i] = has[i-1] * base + s[i];
}
for(int i=1;i<=n;i++)res[i] = 0;
PAT::init(n);
PAT::create(s,n);
PAT::solve();
for(int i=1;i<n;i++)printf("%lld ",res[i]);
printf("%lld\n",res[n]);
}
return 0;
}
第二种方法code
#include <bits/stdc++.h>
using namespace std;
const int N = 3e5+10;
typedef long long ll;
char s[N];
ll res[N];
namespace PAT{
const int SZ = 6e5+10;
int ch[SZ][26],fail[SZ],cnt[SZ],len[SZ],tot,last;
int be[SZ],ok[SZ];
void init(int n){
for(int i=0;i<=n+10;i++){
fail[i] = cnt[i] = len[i] = 0;
for(int j=0;j<26;j++)ch[i][j] = 0;
be[i] = ok[i] = 0;
}
s[0] = -1;fail[0] = 1;last = 0;
len[0] = 0;len[1] = -1;tot = 1;
}
inline int newnode(int x){
len[++tot] = x;return tot;
}
inline int getfail(int x,int n){
while(s[n-len[x]-1] != s[n])x = fail[x];
return x;
}
void create(char *s){
s[0] = -1;
for(int i=1;s[i];++i){
int t = s[i]- 'a';
int p = getfail(last,i);
if(!ch[p][t]){
int q = newnode(len[p]+2);
fail[q] = ch[getfail(fail[p],i)][t];
ch[p][t] = q;
}
++cnt[last = ch[p][t]];
}
}
void solve(){
for(int i=tot;i>=2;i--){
if(be[i] == 0)be[i] = i;
while(be[i] >= 2 && len[be[i]] > (len[i] + 1)/2)be[i] = fail[be[i]];
if(len[be[i]] == (len[i]+1)/2)ok[i] = 1;
be[fail[i]] = be[i];
}
for(int i=tot;i>=2;i--){
cnt[fail[i]] += cnt[i];
if(ok[i]) res[len[i]] += cnt[i];
}
}
}
int main(){
while(~scanf("%s",s+1)){
int n = strlen(s+1);
for(int i=1;i<=n;i++)res[i] = 0;
PAT::init(n);
PAT::create(s);
PAT::solve();
for(int i=1;i<n;i++)printf("%lld ",res[i]);
printf("%lld\n",res[n]);
}
return 0;
}
HDU-6599 I Love Palindrome String(回文自动机+字符串hash)的更多相关文章
- hdu多校第二场1009 (hdu6599) I Love Palindrome String 回文自动机/字符串hash
题意: 找出这样的回文子串的个数:它本身是一个回文串,它的前一半也是一个回文串 输出格式要求输出l个数字,分别代表长度为1~l的这样的回文串的个数 题解: (回文自动机和回文树是一个东西) 首先用回文 ...
- HDU 6599 I Love Palindrome String (回文树+hash)
题意 找如下子串的个数: (l,r)是回文串,并且(l,(l+r)/2)也是回文串 思路 本来写了个回文树+dfs+hash,由于用了map所以T了 后来发现既然该子串和该子串的前半部分都是回文串,所 ...
- [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]也满足 ...
- 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 ...
- CF932G Palindrome Partition(回文自动机)
CF932G Palindrome Partition(回文自动机) Luogu 题解时间 首先将字符串 $ s[1...n] $ 变成 $ s[1]s[n]s[2]s[n-1]... $ 就变成了求 ...
- LeetCode Valid Palindrome 有效回文(字符串)
class Solution { public: bool isPalindrome(string s) { if(s=="") return true; ) return tru ...
- 【CF932G】Palindrome Partition 回文自动机
[CF932G]Palindrome Partition 题意:给你一个字符串s,问你有多少种方式,可以将s分割成k个子串,设k个子串是$x_1x_2...x_k$,满足$x_1=x_k,x_2=x_ ...
- 2019牛客暑期多校训练营(第六场)C - Palindrome Mouse (回文自动机)
https://ac.nowcoder.com/acm/contest/886/C 题意: 给出一个串A , 集合S里面为A串的回文字串 , 现在在集合S里面找出多少对(a,b),b为a的字串 分析: ...
- 杭电多校HDU 6599 I Love Palindrome String (回文树)题解
题意: 定义一个串为\(super\)回文串为: \(\bullet\) 串s为主串str的一个子串,即\(s = str_lstr_{l + 1} \cdots str_r\) \(\bullet\ ...
随机推荐
- node.js 爬取图片
/** * _ooOoo_ * o8888888o * 88" . "88 * (| -_- |) * O\ = /O * ____/`---'\____ * . ' \\| |/ ...
- 【Flutter】可滚动组件之ListView
前言 它可以沿一个方向线性排布所有子组件,并且它也可以支持基于Sliver的延迟构建模型. 接口描述 ListView({ Key key, // 可滚动widget公共参数 Axis scrollD ...
- nginx日志详细说明
Nginx日志主要分为两种:访问日志和错误日志.日志开关在Nginx配置文件(/etc/nginx/nginx.conf)中设置,两种日志都可以选择性关闭,默认都是打开的. 访问日志 访问日志主要记录 ...
- 【MySql】[ERROR] Can't read from messagefile '/usr/share/mysql/english/errmsg.sys'
[root@zhang bin]# ./mysql_install_db --datadir=/usr/local/mysql/mydata/data/ 2018-08-18 03:09:14 [WA ...
- Hadoop 专栏 - MapReduce 入门
MapReduce的基本思想 先举一个简单的例子: 打个比方我们有三个人斗地主, 要数数牌够不够, 一种最简单的方法可以找一个人数数是不是有54张(传统单机计算); 还可以三个人各分一摞牌数各自的(M ...
- 2.4V升3.3V,2.4V升3V,1A大电流升压芯片
两节镍氢电池串联就是1.2V+1.2V=2.4V的供电电压了,2.4V升3V, 2.4V升3.3V的话,就能稳压稳定给模块供电了,镍氢电池是会随着使用的电池电量减少的话,电池的电压也是跟着变化的,导致 ...
- 三十二:WEB漏洞-文件操作之文件下载读取全解
文件下载读取 原路,检测,利用,修复 利用 数据库配置文件下载或者读取后续 接口密钥信息文件下载或者读取后续 文件名,参数值,目录符号 read.xxx?filename= down.xxx?file ...
- 2020 CSP&NOIP 游记
CSP初赛 CSP初赛 Day -1 早上打了模拟赛,T2寒假正好做过,然而还是还是被踩Orz,郑外NB!.中午出校吃了大盘鸡和拉面,还带回来了三瓶可乐. 初赛知识点看了两页不(看)想(不)看(懂)了 ...
- Tensorflow-基础使用
Tensorflow基本概念 使用图(graphs)来表示计算任务 在被称之为会话(Session)的上下文(context)中执行图 使用tensor表示数据 通过变量(Variable)维护状态 ...
- 使用XML作为配置表,WinForm程序读取配置表来动态显示控件
一.首先创建一个XML文件定义以下格式(uName:显示的中文字,uKey:代表控件的Name属性,ukeyValue:代表是否显示) 二.项目中定义一个通用类,来存放读取的值 这三个字段对应XML文 ...