gym101237 C. The Palindrome Extraction(SAM+manecher)
发布日期:2021-06-30 10:32:36 浏览次数:2 分类:技术文章

本文共 3601 字,大约阅读时间需要 12 分钟。

给出一个串 s s s,找出两个不相交的子串 a , b a,b a,b( a a a在前 b b b在后)

满足 a + b a+b a+b是一个回文串


考虑串 ∣ a ∣ > = ∣ b ∣ |a|>=|b| a>=b怎么计算,因为如果 ∣ a ∣ < ∣ b ∣ |a|<|b| a<b,只需要对反串也算一遍就好了

那么一定是 a = b + w a=b+w a=b+w的形式, w w w是一个回文串

我们从回文串下手,枚举每个点 i i i作为回文中心,最长的回文是 [ l , r ] [l,r] [l,r]

那么让 [ l , r ] [l,r] [l,r]作为 w w w,考虑找到一个最小的 i i i满足 [ i , l − 1 ] [i,l-1] [i,l1] [ r + 1 , n ] [r+1,n] [r+1,n]的一个子串

正确性

如果不是最长的回文,比如变成 [ l + 1 , r − 1 ] [l+1,r-1] [l+1,r1],那么最佳情况下 a a a串长度减一, b b b串长度加一,总长度不变

如果回文变成 [ l + 1 , r ] [l+1,r] [l+1,r] [ l , r − 1 ] [l,r-1] [l,r1]也不行,讨论一下就好了

考虑如何求最小的 i i i满足 [ i , l − 1 ] [i,l-1] [i,l1] [ r + 1 , n ] [r+1,n] [r+1,n]的子串

r e v ( S ) rev(S) rev(S)建立 S A M SAM SAM,拿 S S S的每个前缀放在 S A M SAM SAM上匹配记节点为 p o s [ i ] pos[i] pos[i]

我们对 S A M SAM SAM每个节点维护一个 m i i mi_i mii表示最小的 e n d p o s endpos endpos

这样我们就可以快速知道这个节点是否出现在 S S S [ r + 1 , n ] [r+1,n] [r+1,n]中了

因为在反串中出现最早,所以在原串 S S S中最靠右

那么每次只需要把 p o s [ l − 1 ] pos[l-1] pos[l1]向上跳,因为 m i mi mi值父节点必定小于子节点,所以可以倍增快速跳

#include 
using namespace std;#define fi first#define se secondconst int maxn = 4e5+10;typedef pair
mp;mp p1,p2;int ans,n;char a[maxn];int zi[maxn][27],fa[maxn],id,las,l[maxn];int ed[maxn],mi[maxn],st[maxn][22];vector
vec[maxn];void insert(int c,int index){
int p = las, np = ++id; las = id; l[np] = l[p]+1; mi[np] = ed[np] = index;//最早出现的节点 for( ; p&&zi[p][c]==0 ;p=fa[p] ) zi[p][c] = np; if( p==0 ) fa[np] = 1; else {
int q = zi[p][c]; if( l[q]==l[p]+1 ) fa[np] = q; else {
int nq = ++id; memcpy( zi[nq],zi[q],sizeof zi[nq] ); l[nq] = l[p]+1, fa[nq] = fa[q]; mi[nq] = mi[q], ed[nq] = ed[q]; fa[np] = fa[q] = nq; for( ; p&&zi[p][c]==q;p=fa[p] ) zi[p][c] = nq; } }}void dfs(int u){
st[u][0] = fa[u]; for(int i=1;i<=20;i++) st[u][i] = st[st[u][i-1]][i-1]; for( auto v:vec[u] ) {
dfs(v); mi[u] = min( mi[u],mi[v] ); ed[u] = max( ed[u],ed[v] ); }}int pos[maxn],posl[maxn];//分别表示原串中每个前缀在自动机上的位置,和匹配长度 char P[maxn];int pal[maxn];void init(){
memset( st,0,sizeof st ); for(int i=0;i<=id;i++) {
vec[i].clear(); memset( zi[i],0,sizeof zi[i] ); fa[i] = 0; } for(int i=0;i<=n+n+1;i++) pos[i] = posl[i] = pal[i] = 0; id = las = 1;}void work(){
init(); for(int i=1;i<=n;i++) insert( a[i]-'a',i ); for(int i=2;i<=id;i++) vec[fa[i]].push_back( i ); dfs(1); for(int i=n,p=1,le=0;i>=1;i--) {
int c = a[i]-'a'; if( zi[p][c] ) p = zi[p][c],le++; else {
while( p&&zi[p][c]==0 ) p = fa[p]; if( !p ) p = 1,le = 0; else le = l[p]+1, p = zi[p][c]; } pos[i] = p; posl[i] = le; } int C=0,R=0,t=0;P[++t]='#'; for(int i=1;i<=n;i++) P[++t]=a[i],P[++t]='#'; for(int i=1;i<=t;i++) {
if(i<=C+R) pal[i]=min(pal[2*C-i],C+R-i);else pal[i]=0; while(i+pal[i]+1<=t&&i-pal[i]-1>=1&& P[i+pal[i]+1]==P[i-pal[i]-1]) pal[i]++; if(i+pal[i]>=C+R) C=i,R=pal[i]; } for(int i=1;i<=t;i++) if(pal[i]>ans) ans=pal[i], p1=mp((i-pal[i]+1)/2,(i+pal[i]-1)/2), p2=mp(-1,-1); for(int i=1;i<=t;i++) {
if(P[i]=='#'&&pal[i]==0) continue; int zl=(i-pal[i]+1)/2,zr=(i+pal[i]-1)/2; int x=pos[zr+1];//现在回文区间是[zl,zr] for(int w=20;w>=0;w--) if( mi[st[x][w]]>=zl ) x=st[x][w]; if( mi[x]>=zl ) x = st[x][0]; int vl=min( l[x],posl[zr+1] ),v=zr-zl+1+vl*2; if(v>ans) ans=v,p1=mp( ed[x]-vl+1,ed[x] ),p2=mp(zl,zr+vl); } }int main(){
scanf("%s",a+1 ); n = strlen( a+1 ); reverse( a+1,a+1+n ); work(); if(p1.fi!=-1) p1.fi=n-p1.fi+1,p1.se=n-p1.se+1,swap(p1.fi,p1.se); if(p2.fi!=-1) p2.fi=n-p2.fi+1,p2.se=n-p2.se+1,swap(p2.fi,p2.se); reverse( a+1,a+1+n ); work(); if(p1.fi>p2.fi) swap(p1,p2); printf("%d\n%d %d\n%d %d\n",ans,p1.fi,p1.se,p2.fi,p2.se);}

转载地址:https://issue-is-vegetable.blog.csdn.net/article/details/116062949 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:2018 ACM-ICPC, Syrian Collegiate Programming Contest F. Pretests(子集dp)
下一篇:gym/101194 E. Bet(贪心,精度)

发表评论

最新留言

表示我来过!
[***.240.166.169]2024年04月17日 17时22分26秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章

163邮箱域名大全,163邮箱注册申请全流程详解! 2019-04-30
电子邮箱账号申请注册,公司邮件系统哪个好?工作邮箱哪个好? 2019-04-30
怎么申请支持微信登录的企业电子邮箱 2019-04-30
163个人电子邮箱如何申请,邮箱账号都有什么格式你知道吗 2019-04-30
微信企业邮箱登录人口,企业邮箱登陆登录入口 2019-04-30
什么是企业邮箱,如何申请企业邮箱,企业邮箱一年多少钱? 2019-04-30
外贸邮箱选择,外贸企业邮箱注册,海外邮箱申请 2019-04-30
哪家企业邮箱好?免费企业邮箱来一个?邮件服务器谁家好用? 2019-04-30
企业邮箱大全,企业邮箱查询,最大的邮箱是哪个? 2019-04-30
企业邮箱怎么注册流程?企业邮箱域名怎么注册? 2019-04-30
企业电子信箱,电子邮箱格式,企业邮箱怎么注册? 2019-04-30
如何申请企业邮箱注册,如何购买邮箱? 2019-04-30
购买企业邮箱,哪个邮箱最好用?邮件撤回怎么操作? 2019-04-30
电子邮箱是什么?如何申请电子邮箱,申请电子邮箱好处 2019-04-30
如何注册海外邮箱?如何进行邮箱注册163,这些技巧交给你 2019-04-30
企业邮件注册,手机怎么注册邮箱? 2019-04-30
python虚拟环境搭建(virtualenv)、项目依赖快速安装(requirements.txt) 2019-04-30
【转载】舍弃 Python+C,Salesforce 将企业级软件全面迁移到 Go 语言 2019-04-30
MySQL 运行SQL文件 Unknown character set: 'utf8mb4' 2019-04-30
ConnectorStartFailedException 2019-04-30