Gym101237C The Palindrome Extraction Manacher、SAM、倍增
假设字符串\(B,D\)满足\(|B| \geq |D|\),那么一定会有\(B=rev(D)+T\),其中\(T\)是一个回文串。
考虑枚举回文串\(T\)的中心\(p\),找到以\(p\)为中心的最长回文串\(S[l,r]\)。值得注意的是,回文串越长一定越好,因为如果回文串不是最长的,那么可以向左右拓展一位,\(B\)串长度会\(+1\),\(D\)串长度会\(-1\),没有变化。所以我们直接Manacher求最长回文串即可。
现在我们需要求的就是最小的\(i\)满足\(rev(S[i,l-1])\)是\(S[r+1,N]\)的子串。
发现对于所有可能的\(i\)都是\(S[1,l-1]\)的后缀。子串、后缀相关的问题可以考虑后缀自动机。我们对\(rev(S)\)建立SAM,对于SAM上的每一个节点记录最小的\(endpos\),并将\(S\)的所有前缀放到SAM上匹配。那么\(S[i,l-1]\)是SAM的parent树上\(S[1,l-1]\)的祖先。在parent树上倍增就可以得到满足条件的最小的\(i\)。
对于原串和反串各做一遍就可以得到最后的答案。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
//This code is written by Itst
using namespace std;
#define PII pair < int , int >
const int MAXN = 2e5 + 7;
char s[MAXN];
int ind[MAXN] , len[MAXN] , L , ans;
PII ind1 , ind2;
bool flg = 0;
namespace SAM{
char S[MAXN];
int Lst[MAXN] , trans[MAXN][26] , fa[MAXN] , endpos[MAXN] , jump[MAXN][19];
int cnt = 1 , lst = 1;
void insert(int l , int x){
int p = lst , t = ++cnt; lst = t;
Lst[t] = endpos[t] = l;
while(p && !trans[p][x]){trans[p][x] = t; p = fa[p];}
if(!p){fa[t] = 1; return;}
int q = trans[p][x];
if(Lst[q] == Lst[p] + 1){fa[t] = q; return;}
int k = ++cnt; endpos[k] = 1e9;
Lst[k] = Lst[p] + 1;
fa[k] = fa[q]; fa[q] = fa[t] = k;
memcpy(trans[k] , trans[q] , sizeof(trans[q]));
while(trans[p][x] == q){trans[p][x] = k; p = fa[p];}
}
vector < int > ch[MAXN];
void dfs(int x){
for(int i = 1 ; jump[x][i - 1] ; ++i)
jump[x][i] = jump[jump[x][i - 1]][i - 1];
for(auto t : ch[x]){jump[t][0] = x; dfs(t); endpos[x] = min(endpos[x] , endpos[t]);}
}
void init(){
memcpy(S , s , sizeof(S)); reverse(S + 1 , S + L + 1);
for(int i = 1 ; i <= L ; ++i) insert(i , S[i] - 'a');
for(int i = 2 ; i <= cnt ; ++i) ch[fa[i]].push_back(i);
dfs(1);
}
int query(int x , int pos){
if(endpos[x] <= pos) return x;
for(int i = 18 ; i >= 0 ; --i)
if(endpos[jump[x][i]] > pos)
x = jump[x][i];
return jump[x][0];
}
void clear(){
memset(trans , 0 , sizeof(trans)); memset(Lst , 0 , sizeof(Lst));
memset(fa , 0 , sizeof(fa)); memset(endpos , 0 , sizeof(endpos));
memset(jump , 0 , sizeof(jump));
for(int i = 1 ; i <= cnt ; ++i) ch[i].clear();
cnt = lst = 1;
}
}
namespace Manacher{
char S[MAXN];
int Len[MAXN];
void work(){
for(int i = 1 ; i <= L ; ++i)
S[(i << 1) - 1] = s[i];
memset(Len , 0 , sizeof(Len));
int maxR = 1 , maxI = 1;
for(int i = 1 ; i < L << 1 ; ++i){
Len[i] = min(maxR - i , Len[2 * maxI - i]);
while(i - Len[i] >= 0 && i + Len[i] <= L << 1 && S[i - Len[i]] == S[i + Len[i]])
++Len[i];
int posL = (i - Len[i] + 1) / 2 + 1 , posR = (i + Len[i] + 1) / 2 - 1;
if(posL <= posR){
int u = SAM::query(ind[posL - 1] , L - posR) , l = u == ind[posL - 1] ? len[posL - 1] : SAM::Lst[u];
if(ans < posR - posL + 1 + 2 * l){
ans = posR - posL + 1 + 2 * l;
ind1 = PII(posL - l , posR);
if(l) ind2 = PII(L - SAM::endpos[u] + 1 , L - SAM::endpos[u] + l);
else ind2 = PII(-1 , -1);
flg = 1;
}
}
if(maxR <= Len[i] + i){
maxR = Len[i] + i;
maxI = i;
}
}
}
}
void work(){
flg = 0;
SAM::init(); ind[0] = 1;
for(int i = 1 ; i <= L ; ++i){
int cur = ind[i - 1] , l = len[i - 1];
while(cur && !SAM::trans[cur][s[i] - 'a']) l = SAM::Lst[cur = SAM::fa[cur]];
!cur ? ind[i] = 1 : (ind[i] = SAM::trans[cur][s[i] - 'a'] , len[i] = l + 1);
}
Manacher::work();
}
int main(){
scanf("%s" , s + 1);
L = strlen(s + 1); work();
reverse(s + 1 , s + L + 1); SAM::clear(); work();
if(flg){
swap(ind2 , ind1); swap(ind1.first , ind1.second); swap(ind2.first , ind2.second);
ind1.first = L + 1 - ind1.first; ind1.second = L + 1 - ind1.second;
ind2.first = L + 1 - ind2.first; ind2.second = L + 1 - ind2.second;
}
printf("%d\n%d %d\n%d %d\n" , ans , ind1.first , ind1.second , ind2.first , ind2.second);
return 0;
}
Gym101237C The Palindrome Extraction Manacher、SAM、倍增的更多相关文章
- bzoj 3676 [Apio2014]回文串(Manacher+SAM)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3676 [题意] 给定一个字符串,定义一个串的权值为长度*出现次数,求最大权的回文子串. ...
- Codeforces Gym 100570 E. Palindrome Query Manacher
E. Palindrome QueryTime Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100570/pro ...
- Palindrome(Manacher)
Palindrome Time Limit: 15000MS Memory Limit: 65536K Total Submissions: 6183 Accepted: 2270 Descr ...
- Codeforces Beta Round #7 D. Palindrome Degree manacher算法+dp
题目链接: http://codeforces.com/problemset/problem/7/D D. Palindrome Degree time limit per test1 secondm ...
- [BZOJ3676][APIO2014]回文串(Manacher+SAM)
3676: [Apio2014]回文串 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 3097 Solved: 1408[Submit][Statu ...
- POJ3974:Palindrome(Manacher模板)
Palindrome Time Limit: 15000MS Memory Limit: 65536K Total Submissions: 14021 Accepted: 5374 题目链接 ...
- Ural 1297 Palindrome(Manacher或者后缀数组+RMQ-ST)
1297. Palindrome Time limit: 1.0 second Memory limit: 64 MB The “U.S. Robots” HQ has just received a ...
- CF666E Forensic Examination SAM+倍增,线段树和并
题面: 给你一个串S以及一个字符串数组T[1..m],q次询问,每次问S的子串S[p_l..p_r]在T[l..r]中的哪个串里的出现次数最多,并输出出现次数.如有多解输出最靠前的那一个. 分析: 第 ...
- CF 666E Forensic Examination 【SAM 倍增 线段树合并】
CF 666E Forensic Examination 题意: 给出一个串\(s\)和\(n\)个串\(t_i\),\(q\)次询问,每次询问串\(s\)的子串\(s[p_l:p_r]\)在串\(t ...
随机推荐
- Python Python实现批量安装android apk包
基于Python实现批量安装android apk包 by:授客 QQ:1033553122 1.相关软件包及文件下载 下载地址:adb软件包及批量安装apk包的py文件.zip 2.测试环境 Win ...
- 图说OOP基础(一)
本文用图形化的形式描述OOP的相关知识.对OOP进行系统化的梳理,以便掌握,仅供学习分享使用,如有不足之处,还请指正. 涉及知识点: OOP的相关知识 OOP知识总图 [Object-Orientat ...
- Android为TV端助力 bitmap和数据流的互转
Bitmap aa = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher); InputStream input ...
- 2017.9.16~17,热烈庆祝共创力罗老师《敏捷MINI体验式实战培训》在某大型企业成功举办!
2017.9.16~17日,深圳市共创力企业管理咨询有限公司为某上市企业提供了为期两天的内训服务.该次内训的主题为<敏捷MINI体验式实践培训>,为期两天.此次培训由共创力资深讲师Geor ...
- 口碑订单,ERP本地加/退菜无法回流至手机端的解决办法-订单金额不统一erp本地加菜H5没有
关于 口碑订单,ERP本地加/退菜无法回流至手机端的解决办法-订单金额不统一erp本地加菜H5没有 1. 2. 3. PS:是正餐后付的务必要选择口碑后付 完成以上设置即可
- 使用Visual Studio Team Services敏捷规划和项目组合管理(三)——使用Kanban板
使用Visual Studio Team Services敏捷规划和项目组合管理(三)--使用Kanban板 1.要查看Kanban板,请单击Work>Backlogs页面上的Board 链接. ...
- Linux修改挂载目录名称
Local系统管理员新增了一个VG,将一个原挂载点/u02改为了/u02-old, 如下所示. [root@mylnx01 ~]# df -h Filesystem Size ...
- 老K漫谈区块链的共识(3)——分布式系统和区块链共识
1. 啥是分布式系统 当我们评价一个新的事物或者介绍一个新的技术的时候,我们不能架空历史和环境,新的事物不可能脱离历史和环境凭空诞生.任何新的事物和新的技术总是或多或少的,与旧的事件以及过去的技术有所 ...
- Jenkins2.32用户和权限管理策略
前言 在使用jenkins的过程中,需要为不同的角色分配相应的权限,如果jenkins的用户数据能和公司现在的帐号系统结合起来那会更好. 关于如何为用户分组,我推荐使用 role based auth ...
- Linux安装Python3后,如何使用pip命令
系统环境:CentOS7.4 已安装好Python3.6.5 Python3.6.5自带pip 使用pip安装第三方库,可运行指令,例如安装paramiko库: python -m pip insta ...