牛客 14894 最长回文

牛客 14894 最长回文

题目链接

题目描述

有两个长度均为n的字符串A和B。可以从A中选一个可以为空的子串A[l1…r1],B中选一个可以为空的子串B[l2…r2],满足r1=l2,然后把它们拼起来(A[l1…r1]+B[l2…r2])。求用这样的方法能得到的最长回文串的长度。注意:求的不是本质不同的回文串个数哦!!!

输入描述:

第一行一个数n
第二行表示字符串A
第三行表示字符串B

输出描述:

输出一行一个数表示答案

示例1

输入

5
ZQZFC
NSZXL

输出

3

示例2

输入

7
NSZQZFC
CFZQZSN

输出

8

这题先用Manacher算法跑一遍A和B,然后枚举出A和B的最长回文串长度,以此为回文串的中心遍历找最长回文串,注意要错开一个位置,这样找才是最长的,AC代码如下:

#include
using namespace std;
typedef long long ll;
const int N=1e5+5;
char p1[N],p2[N];
char s1[N<<1],s2[N<<1];
int l1[N<<1],l2[N<<1],n;
 
void change(char *p,char *s){
    int i,len=strlen(p);
    s[0]='@';
    for(int i=1;i<=2*len;i+=2){
        s[i]='#';
        s[i+1]=p[i>>1];
    }
    s[2*len+1]='#';
    s[2*len+2]='$';
    s[2*len+3]='\0';
}
 
void manacher(char *s,int *l,int len){
    int mx=0,pos=0;
    for(int i=1;i<=len;i++){
        if(mx>i) l[i]=min(mx-i,l[2*pos-i]);
        else l[i]=1;
        while(s[i-l[i]]==s[i+l[i]]) l[i]++;
        if(l[i]+i>mx){
            mx=l[i]+i;
            pos=i;
        }
    }
}
 
 
int main(){
    scanf("%d%s%s",&n,p1,p2);
    change(p1,s1);
    manacher(s1,l1,2*n+1);
    change(p2,s2);
    manacher(s2,l2,2*n+1);
    int ans=0;
    for(int i=2;i<2*n+1;i++){
        int temp=max(l1[i],l2[i-2]);
        while(s1[i-temp]==s2[i-2+temp]) temp++;
        ans=max(ans,temp);
    }
    cout<<ans-1;
    return 0;
}

你可能感兴趣的:(Manacher,牛客,贪心)