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\ ...
随机推荐
- Mac pycharm更换版本后打不开
1.第一步:先输入: cd /Applications/PyCharm.app/Contents/MacOS 2.第二步:查看无法打开pycharm的原因,需要输入:c./pycharm 3.第三 ...
- 有了链路日志增强,排查Bug小意思啦!
在工作中,相信大家最怕的一件事就是听到有人在工作群艾特你:某某功能报错啦... 然后你就得屁颠屁颠的去服务器看日志,日志量少还好点,多的话找起来太麻烦了.不太容易直接定位到关键地方. 东找找西找找,好 ...
- 修改hosts文件后不生效,该怎么办
对于web开发来说,经常需要修改hosts文件,用来将域名与ip对应匹配.但是有时候发现hosts文件明明已经改了,但就是不生效,页面还会跳到某个丧心病狂的私人小站.hosts文件不生效有很多种原因, ...
- Lambda表达式你会用吗?
函数式编程 在正式学习Lambda之前,我们先来了解一下什么是函数式编程 我们先看看什么是函数.函数是一种最基本的任务,一个大型程序就是一个顶层函数调用若干底层函数,这些被调用的函数又可以调用其他函数 ...
- 【Oracle】10g查看trace生成文件位置及文件名称
select u_dump.value || '/' || db_name.value || '_ora_' || v$process.spid || nvl2(v$process.trace ...
- 透过现象看本质:Java类动态加载和热替换
摘要:本文主要介绍类加载器.自定义类加载器及类的加载和卸载等内容,并举例介绍了Java类的热替换. 最近,遇到了两个和Java类的加载和卸载相关的问题: 1) 是一道关于Java的判断题:一个类被首次 ...
- 记一次使用logmnr查找操作人流程
经常遇到开发的需求,帮我查一下是谁修改了表里面的记录,是谁对表进行了DDL操作,此类问题可以使用logmnr解决 1.根据操作时间定位归档日志 SELECT name FROM V$ARCHIVED_ ...
- SAP client锁定
今天发现一个函数可以锁定SAP CLIENT . SCCR_LOCK_CLIENT 参数是client号码. 还可以通过事物SU10批量锁定用户登陆client
- 深入研究.NET 5的开放式遥测
OpenTelemetry 介绍 OpenTelemetry是一种开放的源代码规范,工具和SDK,用于检测,生成,收集和导出遥测数据(指标,日志和跟踪),开放遥测技术得到了Cloud Native C ...
- Cookie&Session&Jsp总结
知识点梳理 Cookie&Session&Jsp 1 会话技术 1.1 会话管理概述 1.1.1 会话技术介绍 会话:浏览器和服务器之间的多次请求和响应 (一次对话) 为了实现一些功能 ...