列表

详情


NC200546. 回文串

描述

给出一个字符串,从中找出两个不相交且长度和最大非空回文子串,输出长度和。

输入描述

一行一个只由小写字母组成的字符串 S 。
保证  。

输出描述

一行一个整数,表示答案。

示例1

输入:

abccbaa

输出:

7

说明:

第一个回文串为 "abccba",第二个回文串为 "a" 长度和为 7

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 21ms, 内存消耗: 5580K, 提交时间: 2020-06-17 11:05:04

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int N=4e6+5;
char s[N],t[N];
int n,mr,mid,ans,r[N],f[N],g[N];
void manacher(char *t,int *f)
{
    r[0]=1;
    for(int i=1; i<=n; i++)
    {
        r[i]=0;
        if(i<mr)
            r[i]=min(r[mid*2-i],mr-i);
        while(t[i+r[i]]==t[i-r[i]]&&i-r[i]>=0)
            f[i+r[i]]=max(f[i+r[i]],r[i]+1),++r[i];
        if(i+r[i]>mr)
            mid=i,mr=i+r[i];
    }
}
int main()
{
    scanf("%s",s),n=strlen(s);
    for(int i=0; i<n; i++)
        t[i*2]='#',t[i*2+1]=s[i];
    t[n*2]='#',n<<=1;
    manacher(t,f),reverse(t,t+n+1),manacher(t,g);
    for(int i=1; i<=n; i++)
        f[i]=max(f[i],f[i-1]);
    for(int i=1; i<=n; i++)
        g[i]=max(g[i],g[i-1]);
    for(int i=1; i<n; i++)
    {
        if(i&1)
            ans=max(ans,f[i+1]+g[n-i-1]-2);
        else
            ans=max(ans,f[i]+g[n-i]-2);
    }
    printf("%d\n",ans);
    return 0;
}

C++11(clang++ 3.9) 解法, 执行用时: 26ms, 内存消耗: 5752K, 提交时间: 2020-01-10 22:07:55

#include<bits/stdc++.h>
using namespace std;
const int N=4e6+5;
char s[N],t[N];
int n,mr,mid,ans,r[N],f[N],g[N];
void manacher(char *t,int *f){
	r[0]=1;
	for(int i=1;i<=n;i++){
		r[i]=0;
		if(i<mr)	r[i]=min(r[mid*2-i],mr-i);
		while(t[i+r[i]]==t[i-r[i]]&&i-r[i]>=0)
			f[i+r[i]]=max(f[i+r[i]],r[i]+1),++r[i];
		if(i+r[i]>mr)	mid=i,mr=i+r[i];
	}
}
int main(){
	scanf("%s",s),n=strlen(s);
	for(int i=0;i<n;i++)
		t[i*2]='#',t[i*2+1]=s[i];
	t[n*2]='#',n<<=1;
	manacher(t,f),reverse(t,t+n+1),manacher(t,g);
	for(int i=1;i<=n;i++)	f[i]=max(f[i],f[i-1]);
	for(int i=1;i<=n;i++)	g[i]=max(g[i],g[i-1]);
	for(int i=1;i<n;i++){
		if(i&1)	ans=max(ans,f[i+1]+g[n-i-1]-2);
		else	ans=max(ans,f[i]+g[n-i]-2);
	}
	printf("%d\n",ans);
	return 0;
}

上一题