【题目链接】

  • 点击打开链接

【思路要点】

  • 一定存在一个最长的扭动回文串是从回文中心所在串的某一个极长回文子串开始,一侧向回文中心所在串匹配,另一侧扭向另一个串匹配。因为任意一个扭动的回文串都对应了一个同样长的满足上述要求的扭动的回文串。
  • 枚举回文中心,问题转化为了两个字符串的LCP,字符串哈希和后缀结构均可解决。
  • 时间复杂度\(O(NLogN)\)。

【代码】

#include<bits/stdc++.h>
using namespace std;
#define MAXN    400005
#define MAXLOG  20
int n, lenx[MAXN], leny[MAXN];
char x[MAXN], y[MAXN];
int homex[MAXN], homey[MAXN];
int Manacher(char *x, int *len) {static char s[MAXN];for (int i = 1; i <= n; i++) {s[i * 2] = x[i];s[i * 2 - 1] = '#';}s[0] = '$'; s[n * 2 + 1] = '#';s[n * 2 + 2] = '$';int pos = 0, home = 0, ans = 0;for (int i = 1; i <= 2 * n + 1; i++) {if (i > pos) {len[i] = 1;while (s[i - len[i]] == s[i + len[i]])len[i]++;pos = i + len[i] - 1;home = i;} else {int p = home * 2 - i;if (i + len[p] - 1 < pos) len[i] = len[p];else {len[i] = pos - i + 1;while (s[i - len[i]] == s[i + len[i]])len[i]++;pos = i + len[i] - 1;home = i;}}ans = max(ans, len[i] - 1);}return ans;
}
struct Suffix_Automaton {int child[MAXN][26];int father[MAXN], depth[MAXN];int parent[MAXN][MAXLOG], cnt[MAXN];vector <int> a[MAXN];int root, size, last;int new_node(int dep) {depth[size] = dep;father[size] = 0;a[size].clear();memset(child[size], 0, sizeof(child[size]));memset(parent[size], 0, sizeof(parent[size]));return size++;}void init() {size = 0;root = new_node(0);}void Extend(int ch) {int np = child[last][ch];if (np) {if (depth[last] + 1 == depth[np]) last = np;else {int nq = new_node(depth[last] + 1);father[nq] = father[np];father[np] = nq;memcpy(child[nq], child[np], sizeof(child[np]));for (int p = last; child[p][ch] == np; p = father[p])child[p][ch] = nq;last = nq;}} else {np = new_node(depth[last] + 1);int p = last;for (; child[p][ch] == 0; p = father[p])child[p][ch] = np;if (child[p][ch] == np) last = np;else {int q = child[p][ch];if (depth[q] == depth[p] + 1) {father[np] = q;last = np;} else {int nq = new_node(depth[p] + 1);father[nq] = father[q];father[q] = father[np] = nq;memcpy(child[nq], child[q], sizeof(child[q]));for (; child[p][ch] == q; p = father[p])child[p][ch] = nq;last = np;}}}}void insert(char *s, int *home) {int len = strlen(s + 1);last = root;for (int i = 1; i <= len; i++) {Extend(s[i] - 'A');home[i] = last;}}void work(int pos, int depth) {cnt[pos] = depth;parent[pos][0] = father[pos];for (int i = 1; i < MAXLOG; i++)parent[pos][i] = parent[parent[pos][i - 1]][i - 1];for (unsigned i = 0; i < a[pos].size(); i++)work(a[pos][i], depth + 1);}void build() {for (int i = 1; i < size; i++)a[father[i]].push_back(i);work(root, 0);}int query(int x, int y) {if (cnt[x] < cnt[y]) swap(x, y);for (int i = MAXLOG - 1; i >= 0; i--)if (cnt[parent[x][i]] >= cnt[y]) x = parent[x][i];if (x == y) return depth[x];for (int i = MAXLOG - 1; i >= 0; i--)if (parent[x][i] != parent[y][i]) {x = parent[x][i];y = parent[y][i];}return depth[father[x]];}
} SAM;
int main() {freopen("BZOJ4755.in", "r", stdin);freopen("BZOJ4755.out", "w", stdout);scanf("%d\n%s\n%s", &n, x + 1, y + 1);int ans = max(Manacher(x, lenx), Manacher(y, leny));SAM.init();SAM.insert(x, homex);for (int i = 1, j = n; i < j; i++, j--)swap(y[i], y[j]);SAM.insert(y, homey);for (int i = 1, j = n; i < j; i++, j--)swap(homey[i], homey[j]);SAM.build();for (int i = 1; i <= n; i++) {int tmp = lenx[i * 2] / 2;if (tmp == i) continue;ans = max(ans, 2 * SAM.query(homex[i - tmp], homey[i + tmp - 1]) + tmp * 2 - 1);}for (int i = 1; i < n; i++) {int tmp = lenx[i * 2 + 1] / 2;if (tmp == i) continue;ans = max(ans, 2 * SAM.query(homex[i - tmp], homey[i + tmp]) + tmp * 2);}for (int i = 1; i <= n; i++) {int tmp = leny[i * 2] / 2;if (i + tmp > n) continue;ans = max(ans, 2 * SAM.query(homex[i - tmp + 1], homey[i + tmp]) + tmp * 2 - 1);}for (int i = 1; i < n; i++) {int tmp = leny[i * 2 + 1] / 2;if (i + tmp + 1 > n) continue;ans = max(ans, 2 * SAM.query(homex[i - tmp + 1], homey[i + tmp + 1]) + tmp * 2);}printf("%d\n", ans);return 0;
}

【BZOJ4755】【JSOI2016】扭动的回文串相关推荐

  1. bzoj4755: [Jsoi2016]扭动的回文串 manacher+二分+Hash

    bzoj4755: [Jsoi2016]扭动的回文串 Description JYY有两个长度均为N的字符串A和B. 一个"扭动字符串S(i,j,k)由A中的第i个字符到第j个字符组成的子串 ...

  2. BZOJ4755 [Jsoi2016]扭动的回文串

    标签:Manacher,hash,二分 题目 题目传送门 Description JYY有两个长度均为N的字符串A和B. 一个"扭动字符串S(i,j,k)由A中的第i个字符到第j个字符组成的 ...

  3. BZOJ4755: [JSOI2016]扭动的回文串——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=4755 JYY有两个长度均为N的字符串A和B. 一个"扭动字符串S(i,j,k)由A中的第 ...

  4. 【BZOJ4755】 [Jsoi2016]扭动的回文串

    BZOJ4755 [Jsoi2016]扭动的回文串 Solution 考虑对于他给出的 A中的一个回文串: B中的一个回文串: 或者某一个回文的扭动字符串S(i,j,k) 这样子几个限制,我们1,2就 ...

  5. [BZOJ]4755: [Jsoi2016]扭动的回文串

    Time Limit: 10 Sec  Memory Limit: 512 MB Description JYY有两个长度均为N的字符串A和B. 一个"扭动字符串S(i,j,k)由A中的第i ...

  6. [JSOI2016]扭动的回文串

    题目 非常板子了 看到求什么最长的回文,我们就想到枚举回文中心的方法 首先对于这个回文串只包含在一个串内的情况,我们随便一搞就可以了,大概\(Manacher\)一下就没有了 对于那种扭动的回文串,我 ...

  7. bzoj 4755: [Jsoi2016]扭动的回文串 manachar+hash+二分

    题意 JYY有两个长度均为N的字符串A和B. 一个"扭动字符串S(i,j,k)由A中的第i个字符到第j个字符组成的子串与B中的第j个字符到第k个字符组成的子串拼接而成. 比如,若A='XYZ ...

  8. 洛谷 P4324 [JSOI2016]扭动的回文串 manacher+字符串hash

    题目描述 JYY有两个长度均为 NNN 的字符串 AAA 和 BBB. 一个扭动字符串 S(i,j,k)S(i,j,k)S(i,j,k) 由 AAA 中的第 iii 个字符到第 jjj 个字符组成的子 ...

  9. P4324 [JSOI2016]扭动的回文串

    传送门 对\(A\).\(B\)串各跑一遍\(manacher\),求出第\(1\).\(2\)类扭动回文串的最大长度. 考虑第三类的扭动回文串\(S(i,j,k)\),一定可以表示为\(A(i,l) ...

最新文章

  1. C语言解析pcap文件得到HTTP信息实例(原创,附源码)
  2. 我眼中的Linux设备树(四 中断)
  3. 腾讯云 视频 点播 视频上传接口
  4. 读取CSV内容,根据不同的图片标签放到指定文件夹
  5. CI框架源码阅读笔记8 控制器Controller.php
  6. Elasticsearch SQL介绍及实例
  7. 1到100猜数字游戏规则c语言,[C语言课程设计猜数字游戏1.doc
  8. 20140704笔试面试总结(java)
  9. 通过实现网站访问计数器带你理解 轻量级锁CAS原理,还学不会算我输!!!
  10. Python 设计模式之建造者模式 Builder Pattern
  11. python错误笔记
  12. Binder机制(非常好理解)
  13. MCGS洗衣机模拟仿真 组态王洗衣机模拟仿真
  14. 关于MATLAB未定义函数或变量 ‘wavread‘的很简单的解决办法
  15. 参考文献名称怎么复制_论文格式之注释:脚注、尾注、参考文献怎么弄?
  16. 青年大学习自动名单核对程序
  17. iOS 2018 面试法宝(绝密文件)1
  18. Paper Reading - 基础系列 - 常用评价指标 ROC、PR、mAP
  19. zcu102网口不通
  20. 基于Mind+、MOTT实现人工智能

热门文章

  1. Android清洁架构(一)
  2. 金多多看盘新周期还在路上
  3. 使用AutoIt自动登录sohu搜狐网页邮箱的代码
  4. qt中制作添加 .ts 翻译文件
  5. MySQL查询近7天、1年、5年内数据,无数据部分补0
  6. 微信小程序参数二维码的8大使用场景
  7. keil编译代码Program Size详解
  8. Python:利用Pillow库创建字符画
  9. win7 QQ自动远程协助 提示关闭了远程桌面
  10. python中字符串和文本处理(很详细)