题目链接

题意:给定一个字符串\(|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;
}

转载于:https://www.cnblogs.com/1625--H/p/11288662.html

HDU-6599 I Love Palindrome String(回文自动机+字符串hash)相关推荐

  1. HDU - 6599 I Love Palindrome String (回文树+Manacher、回文树+hash)

    题目链接 题意 一个长度为3e5的字符串,求长度为iii的字符串满足字符是回文串而且字符串的前一半也是回文串的个数 思路 回文数求出所有的回文字符串,然后用Manacher或者Hash判断是否符合条件 ...

  2. HDU - 5157 Harry and magic string(回文自动机)

    题目链接:点击查看 题目大意:给出一个字符串 s ,问字符串 s 中有多少对回文子串(x,y),意思就是子串 x 和子串 y 都是回文串,且不相交(不重叠) 题目分析:可以正着跑一遍回文自动机,用一个 ...

  3. 【题解】HDU6599 I Love Palindrome String 回文自动机

    补一下多校里碰到的字符串题. 来源:2019 HDU Multi-University Training Contest 2 - 09 给定一个字符串S,对于每个i,输出有多少个子串s[l,r]满足以 ...

  4. CodeForces - 932G Palindrome Partition(回文自动机+Palindrome Series优化dp)

    题目链接:点击查看 题目大意:给出一个长度为偶数的字符串,问将其分割成 k 个子串记为 a[ 1 ] , a[ 2 ] ... a[ k ] ,且满足 a[ i ] == a[ k - i + 1 ] ...

  5. HDU - 5394 Trie in Tina Town(回文自动机+字典树)

    题目链接:点击查看 题目大意:给出一个字典树,现在需要求出字典树上所有的回文串做出的贡献,为 出现次数*回文串长度,求出这个答案 题目链接:可以直接在字典树上dfs然后维护贡献,不过这就涉及到了回文自 ...

  6. HDU 6599:I Love Palindrome String Manacher+回文自动机

    题意 Problem Description You are given a string S=s1s2-s|S| containing only lowercase English letters. ...

  7. HDU6599I Love Palindrome String 回文树+哈希

    点我看题 题意: 给出一个长度为N的字符串,要求输出一个长度为N的数组A, A[i]表示长度为i的good substring的数量 good substring 的定义是 该子串是回文串,且该子串的 ...

  8. hdu 6599 I Love Palindrome String hash+PAM

    题意 给一个字符串,让我们找每个长度的子串中,是super串的个数.(类似双倍回文) 分析 我们对原串建立一个PAM,这样我们可以统计每种回文串出现次数,在用hash判断是不是super串 最后在统计 ...

  9. POJ--3974 Palindrome(回文串,hash)

    链接:点击这里 #include<iostream> #include<algorithm> #include<stdio.h> #include<cstri ...

最新文章

  1. 第十一届蓝桥杯省赛第一场C++A/B组真题【未完结】
  2. (转载)一套完整的UI设计规范手册(IOS版)
  3. 如何获取Kafka的消费者详情——从Scala到Java的切换
  4. hdu 3951 硬币围成一圈(博弈)
  5. php网页如何做出透明的效果,css+filter实现简单的图片透明效果
  6. centos mysql5.6.35_centos6.8 mysql 5.6.35 glibc安装
  7. linux中wget 、apt-get、yum rpm区别
  8. 简单使用linux感受,linux小白说说用linux的感受
  9. 发布后500访问错误 —— dll引用错误
  10. oracle crm客户关系管理资料下载_悟空CRM:使用CRM系统进行客户关系管理的要点...
  11. PHP 中华如何用命令连接数据库,教你如何用php pdo连接数据库
  12. [00011]-[2015-08-26]-[00]-[Windows 程序设计 ---MFC 截屏---BMP格式 ---JPG格式]
  13. python关机_Python 神操作: 远程开机和关机
  14. 大部分程序员还不知道的 Servelt3 异步请求,原来这么简单?
  15. XXL-API v1.1.1 发布,API管理平台
  16. 数据分析必备的五大能力
  17. 台式电脑windows10蓝屏代码 SYSTEN_THREAD_EXCEPTION_NOT_HANDLED 失败的操作rtl8188gu.sys
  18. 《信号与系统学习笔记》—线性时不变系统(一)
  19. 经典SQL语句大全:http://www.cnblogs.com/yubinfeng/archive/2010/11/02/1867386.html
  20. linux发音,你发对了吗

热门文章

  1. Sicily 1817 校歌手大奖赛
  2. BZOJ4066:简单题(K-D Tree)
  3. Django创建项目
  4. 轻松精通数据库管理之道——运维巡检之四(数据库备份)
  5. ORA-10997:another startup/shutdown operation of this instance in progress解决方法
  6. 随机生成 字体大小--转
  7. redhat es4 u5 下安装ORACLE 11G.
  8. protobuf的安装和卸载
  9. Win7局域网打印机共享设置(详细图文流程)
  10. kotlin集合操作符——元素操作符