zoukankan      html  css  js  c++  java
  • Luogu P4555 [国家集训队]最长双回文串


    Luogu P4555 [国家集训队]最长双回文串

    解析

    • 看到回文串,先想 Manacher(马拉车) 算法
    • 题目中要求最长双回文串的长度,注意这个双回文串不能有重叠部分,所以我们想到 Manacher 后枚举切断的位置,这个位置只能是 “ # ” ,为了防止时间复杂度退化到 $ n^2 $ ,我们开两个数组 aft 和 bef , $ aft_i $ 表示以 i 为左端点( i 往后)的最长回文串的长度, $ bef_i $ 表示以 i 为右端点( i 往前)的最长回文串的长度

    Code

    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define LL long long
    using namespace std;
    const int N=1e5+5;
    char s[N],sw[2*N];
    int r[2*N],aft[2*N],bef[2*N],ans;
    int pre_deal()
    {
    	int len=strlen(s+1);
    	sw[0]='!';
    	sw[1]='#';
    	int lon=2;
    	for(int i=1;i<=len;i++)
    	{
    		sw[lon++]=s[i];
    		sw[lon++]='#';
    	}
    	sw[lon]='?';
    	return lon;
    }
    void manacher()
    {
    	int len=pre_deal();
    	int id,mx=0;
    	for(int i=1;i<len;i++)
    	{
    		if(i>=mx) r[i]=1;
    		else r[i]=min(r[2*id-i],mx-i);
    		while(sw[i-r[i]]==sw[i+r[i]]) r[i]++;
    		if(mx<i+r[i])
    		{
    			id=i;
    			mx=i+r[i];
    		}
    		aft[i-r[i]+1]=max(aft[i-r[i]+1],r[i]-1);
    		bef[i+r[i]-1]=max(bef[i+r[i]-1],r[i]-1);
    	}
    	for(int i=3;i<=len-1;i+=2) aft[i]=max(aft[i],aft[i-2]-2);
    	for(int i=len-1;i>=1;i-=2) bef[i]=max(bef[i],bef[i+2]-2);
    	for(int i=1;i<=len-1;i+=2) if(aft[i]&&bef[i]) ans=max(ans,aft[i]+bef[i]);
    	printf("%d
    ",ans);
    	return;
    }
    int main()
    {
    	cin>>(s+1);
    	manacher();
    	return 0;
    }
    
  • 相关阅读:
    二叉平衡树
    红黑树
    [leetcode] LCP 比赛
    二叉搜索树
    面向对象的二叉树的实现
    二叉树的序列化与反序列化
    [leetcode] 基本计算器
    【pandas】玩转一行拆多行,多行并一行(分分合合你说了算)
    【VBA】数据溢出与解决
    【VBA】criterial 未找到命名参数
  • 原文地址:https://www.cnblogs.com/Hawking-llfz/p/11506784.html
Copyright © 2011-2022 走看看