题目链接

题意

一个长度为3e5的字符串,求长度为iii的字符串满足字符是回文串而且字符串的前一半也是回文串的个数

思路

回文数求出所有的回文字符串,然后用Manacher或者Hash判断是否符合条件

#include <bits/stdc++.h>
#define LL long long
#define P pair<int, int>
#define lowbit(x) (x & -x)
#define mem(a, b) memset(a, b, sizeof(a))
#define mid ((l + r) >> 1)
#define lc rt<<1
#define rc rt<<1|1
#define endl '\n'
const int maxn = 3e5 + 5;
const int inf = 0x3f3f3f3f;
const int mod = 19930726;
using namespace std;struct Palindrome_Tree{int nex[maxn][26];int fail[maxn], cnt[maxn], num[maxn]; // num 记录每个节点右端点的表示回文串的个数int len[maxn], S[maxn];                 // cnt 记录每个节点表示的回文串出现的次数int last, n, p;int newnode(int l) { // 新建节点for (int i = 0; i < 26; ++i) nex[p][i] = 0;cnt[p] = num[p] = 0;len[p] = l;return p++;}void init() { // 初始化p = 0;newnode(0), newnode(-1); // 新建奇根和偶根last = n = 0;S[n] = -1; fail[0] = 1; // 偶根指向}int get_fail(int x) { // 求failwhile (S[n - len[x] - 1] != S[n]) x = fail[x];return x;}void add(int c) { // 添加节点c -= 'a';S[++n] = c;int cur = get_fail(last);if (!nex[cur][c]) {int now = newnode(len[cur] + 2);fail[now] = nex[get_fail(fail[cur])][c];nex[cur][c] = now;num[now] = num[fail[now]] + 1;}last = nex[cur][c];cnt[last]++;}void count() { // 求cntfor (int i = p - 1; i >= 0; --i) cnt[fail[i]] += cnt[i];}
}Tree;
int RL[maxn << 1];
void Manacher(string s) {string t;for (int i = 0; i < (int)s.size(); ++i) {t += s[i];t += '#';}s = "#" + t;int MaxRight = 0, pos = 0;for (int i = 0; i < (int)s.size(); ++i) {if (i < MaxRight)  RL[i] = min(RL[2 * pos - i], MaxRight - i + 1); // 好多这里写的是 MaxRight - i,个人感觉根据算法思想应该+1计算长度。else   RL[i] = 1;int l = i - RL[i];int r = i + RL[i];while (l >= 0 && r < (int)s.size() && s[l] == s[r])  {RL[i] += 1;l = i - RL[i];r = i + RL[i];}if (RL[i] + i - 1 > MaxRight) {MaxRight = RL[i] + i - 1;pos = i;}}
}
int ans[maxn], pos[maxn];
int main() {ios::sync_with_stdio(0);cin.tie(0), cout.tie(0);string s;while (cin >> s) {int len = s.size();Tree.init();for (int i = 0; i <= len * 2; ++i) RL[i] = 0;for (int i = 1; i <= len; ++i) ans[i] = 0;Manacher(s);for (int i = 0; i < len; ++i) {Tree.add(s[i]);pos[Tree.last] = i; }Tree.count();for (int i = 2; i < Tree.p; ++i) {int t = Tree.len[i] / 2;int idx = (pos[i] - t - (Tree.len[i] - t) / 2) * 2 + 1;if ((Tree.len[i] - t) % 2 == 0) idx += 1;  if (RL[idx] - 1 >= Tree.len[i] - t) {ans[Tree.len[i]] += Tree.cnt[i];}}for (int i = 1; i <= len; ++i) {if (i > 1) cout << " ";cout << ans[i];}cout << endl;}return 0;
}
#include <bits/stdc++.h>
#define LL long long
#define P pair<int, int>
#define lowbit(x) (x & -x)
#define mem(a, b) memset(a, b, sizeof(a))
#define mid ((l + r) >> 1)
#define lc rt<<1
#define rc rt<<1|1
#define endl '\n'
const int maxn = 3e5 + 5;
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + 7;
using namespace std;struct Palindrome_Tree{int nex[maxn][26];int fail[maxn], cnt[maxn], num[maxn]; // num 记录每个节点右端点的表示回文串的个数int len[maxn], S[maxn];                 // cnt 记录每个节点表示的回文串出现的次数int last, n, p;int newnode(int l) { // 新建节点for (int i = 0; i < 26; ++i) nex[p][i] = 0;cnt[p] = num[p] = 0;len[p] = l;return p++;}void init() { // 初始化p = 0;newnode(0), newnode(-1); // 新建奇根和偶根last = n = 0;S[n] = -1; fail[0] = 1; // 偶根指向}int get_fail(int x) { // 求failwhile (S[n - len[x] - 1] != S[n]) x = fail[x];return x;}void add(int c) { // 添加节点c -= 'a';S[++n] = c;int cur = get_fail(last);if (!nex[cur][c]) {int now = newnode(len[cur] + 2);fail[now] = nex[get_fail(fail[cur])][c];nex[cur][c] = now;num[now] = num[fail[now]] + 1;}last = nex[cur][c];cnt[last]++;}void count() { // 求cntfor (int i = p - 1; i >= 0; --i) cnt[fail[i]] += cnt[i];}
}Tree;
int ans[maxn], pos[maxn];
struct Hash{long long p[maxn], hash[maxn], seed = 402653189;long long getHash(int l, int r) {long long ans = (hash[r] - hash[l-1] * p[r-l+1]) % mod;return (ans + mod) % mod;}void init(string s) {int n = s.size();p[0] = 1;for (int i = 1; i <= n; ++i) p[i] = p[i - 1] * seed % mod;for (int i = 1; i <= n; ++i) {hash[i] = (hash[i - 1] * seed % mod + (s[i-1] - 'a' + 1)) % mod;}}
}hash1, hash2;
int main() {ios::sync_with_stdio(0);cin.tie(0), cout.tie(0);string s;while (cin >> s) {int len = s.size();for (int i = 1; i <= len; ++i) ans[i] = 0;Tree.init();for (int i = 0; i < len; ++i) {Tree.add(s[i]);pos[Tree.last] = i; }Tree.count();hash1.init(s);reverse(s.begin(), s.end());hash2.init(s);for (int i = 2; i < Tree.p; ++i) {int t = Tree.len[i] / 2;int l = pos[i] - Tree.len[i] + 2;int r = pos[i] - t + 1;if (hash1.getHash(l, r) == hash2.getHash(len+1-r, len+1-l)) {ans[Tree.len[i]] += Tree.cnt[i];}}for (int i = 1; i <= len; ++i) {if (i > 1) cout << " ";cout << ans[i];}cout << endl;}return 0;
}

HDU - 6599 I Love Palindrome String (回文树+Manacher、回文树+hash)相关推荐

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

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

  2. hdu 6599 I Love Palindrome String hash+PAM

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

  3. 「HDU6599 I Love Palindrome String」 - 回文自动机

    HDU 6599 I Love Palindrome String tags:回文自动机 题意 让你求有多少个 \([l,r]\) 满足 \(s[l,r]\) 和 \(s\left[l,\frac{l ...

  4. I Love Palindrome String HDU - 6599 回文树+hash

    题意: 输出每个长度下的回文串(这些回文串的左半边也需要是回文串) 题解: 直接套上回文树,然后每找到一个回文串就将他hash. 因为符合要求的回文串本身是回文串,左半边也是回文串,所以它左半边也右半 ...

  5. HDU-6599 I Love Palindrome String 杭电第二次多校赛(Manacher+回文自动机)

    HDU-6599 I Love Palindrome String 杭电第二次多校赛(Manacher+回文自动机) 我的博客:https://acmerszq.cn 原题链接:http://acm. ...

  6. leetcode题库:5.最长回文子串Longest Palindrome string

    题目描述: /** 题目地址:https://leetcode-cn.com/problems/longest-palindromic-substring/description/  * 题目:最长回 ...

  7. hdu 6599(回文树+hash)

    题目 思路:先建好一棵回文树,然后问题就是如何快速判断一个结点代表的回文串是不是题目要求的回文串,暴力判断就是顺着后缀链接找,然后就T了 emmm.而实际上在插入一个结点时,这个代表的回文串我们可以通 ...

  8. 2018 ICPC 南京 M. Mediocre String Problem(ExKMP + Manacher / ExKMP+回文树)

    2018 ICPC 南京 全文见:https://blog.csdn.net/qq_43461168/article/details/112796538 M. Mediocre String Prob ...

  9. 最长回文子串和回文链表

    回文子串和回文链表 文章目录 回文子串和回文链表 一.最长回文子串 1.题目描述 2.分析 3.代码实现 二.判断回文链表 1.问题描述 2. 分析 3.代码 4.优化 三.回文子串 1.问题描述 2 ...

最新文章

  1. 索引的工作原理及其优缺点
  2. ubuntu系统home(主文件夹)中的内容在桌面的显示
  3. python psd_Python psd包_程序模块 - PyPI - Python中文网
  4. Thymeleaf模板引擎---SpringBoot
  5. 利用.dSYM和.app文件准确定位Crash位置
  6. NOIP2009 最优贸易
  7. 【JVM】 讲的比较好的JVM博客连接
  8. [单片机]KeilC51简单流水灯制作与原理
  9. htc328d屏幕排线怎么换_HTC T328D中文Recovery刷机教程
  10. 720度全景场景HTML5源码,直接在浏览器中运行
  11. 《企业大数据系统构建实战:技术、架构、实施与应用》一2.3 大数据制度和流程规范...
  12. 海洋CMS采集-内置接口的海洋CMS采集
  13. 关于SPSS软件中的多选题如何处理呢?
  14. photoshop入门笔记1:PS的快捷键
  15. cxf调用报错Could not find conduit initiator for address:
  16. python做三国杀
  17. 1. 通用基础算法(1.7动态规划算法/1.8模拟算法/1.9其他算法)
  18. ARM微控制器与嵌入式系统 基础知识
  19. 单片机开发用到的intrins.h文件
  20. 百度地图API支持HTTPS

热门文章

  1. [BZOJ 2438] [中山市选2011]杀人游戏 Tarjan缩点
  2. 【UI】android如何绘制一个饼图
  3. 水晶报表使用经验谈1--建立水晶报表第一步及编译最易出现错误的解决方法及报表转换成pdf文档进行打印方法...
  4. [基础题] 7.第一种(*)按如下要求编写Java程序:
  5. Maven中使用tomcat:run出现错误org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException
  6. iOS之深入解析GCD的底层原理
  7. Django Model 自动生成 E-R 图
  8. 2013年第四届蓝桥杯C/C++ A组国赛 —— 第一题:填算式
  9. ZYAR20A 亚克力2驱 蓝牙 298寻迹避障机器人 —— 小车红外避障实验(带后退掉头避障)
  10. 【Tools】Modbus Slave 7安装详解