仔细分析,逐个击破

思路:先分析双回文串的性质,即一个 长度为4的倍数(条件1)左右两部分相等(条件2)左右两部分都为长度为偶数的回文串(条件3)回文串(条件4)
可以看出,当满足条件2,3,4时,条件1自动满足(这个特别明显,看不出来可以自己画一下),所以可以不用特别考虑条件1
又可以看出,当满足条件2,4时,条件3自动满足,当满足条件3,4时,条件2自动满足(这个也很明显),所以条件2,3只需要考虑其中一个即可
所以,问题从需要考虑4个条件变成了考虑2个条件
遇到求回文串的题目,看看一些基本算法好像无法解决,肯定会先往manacher和PAM方面想的
先想想manacher算法应该如何解决这个问题
满足条件4?简单,manacher秒了
问题来到如何满足条件2或3的其中一个
我们看看manacher算法的内部(这里采用分开计算d1,d2,即以i为中心的长度为奇数/偶数的回文串个数,且由于这题只需要长度为偶数,所以只需要求d2)
void manacher(){
    for(int i=0,l=0,r=-1;i<n;i++){
        int k=(i>r) ? 0 : min(d2[l+r-i+1],r-i+1);
        while(0<=i-k-1 && i+k<n && s[i-k-1]==s[i+k]){
            k++;
        }
        d2[i]=k--;
        if(i+k>r){
            l=i-k-1;
            r=i+k;
        }
    }
    return ;
}
观察此处
while(0<=i-k-1 && i+k<n && s[i-k-1]==s[i+k]){
    k++; //左右两个字符相同,以i为中心的长度为偶数的回文串长度+1
}
我们知道,回文串原本就有左右对称的性质,如果考虑用代码实现条件2,需要求解左右相等,这看上去有点麻烦,因为看上去需要再开一个for循环,时间复杂度会有问题,我们期望能够O(1)实现这种双倍回文串的判定
考虑用代码实现条件3,需要求解左右两部分都为偶数的回文串
看看代码,当manacher跑到下标为i时,当回文半径为k时,说明左右两边的长度都为k
那么,当k为偶数时,左右两部分都为偶数,条件3的前半部分满足了

现在考虑后半部分,即左右都为回文
由于双倍回文串左右对称的性质,所以可以只考虑一边回文的情况,如左边回文
再看看代码,当manacher跑到下标为i时,说明之前的下标都已经计算完毕了
那么,既然此时回文半径为k,说明左侧回文的偶数中心j为i-(k/2)
找到这个偶数中心,可以使用其d2,看d2[j]是否>=( k / 2 ),是的话说明左侧是回文的,右侧由于对称也是回文的,条件3成立,做完了

看看时间复杂度,manacher为O(n),里面的判定字符串为O(1)
核心代码如下
while(0<=i-k-1 && i+k<n && s[i-k-1]==s[i+k]){
    k++;
    if(!(k&1)){ //双倍回文的左边的串长度为偶数才考虑 
        int j=i-(k>>1); //找到双倍回文的左边的串的中间部分 
		if(j>=0){
			if(d2[j]>=(k>>1)){ //左边为回文串时,无需判断右边,因为k能够到这里,说明右边和左边对称,一定回文 
				maxn=max(maxn,k<<1);
			}
		} 
	}
}
主代码如下
int d2[N]; 
//d2:以i为中心的长度为偶数的回文串个数
char s[N];
int n;
int maxn;

void manacher(){
    for(int i=0,l=0,r=-1;i<n;i++){
        int k=(i>r) ? 0 : min(d2[l+r-i+1],r-i+1);
        while(0<=i-k-1 && i+k<n && s[i-k-1]==s[i+k]){
            k++;
            if(!(k&1)){ //双倍回文的左边的串长度为偶数才考虑 
            	int j=i-(k>>1); //找到双倍回文的左边的串的中间部分 
				if(j>=0){
					if(d2[j]>=(k>>1)){ //左边为回文串时,无需判断右边,因为k能够到这里,说明右边和左边对称,一定回文 
						maxn=max(maxn,k<<1);
					}
				} 
			}
        }
        d2[i]=k--;
        if(i+k>r){
            l=i-k-1;
            r=i+k;
        }
    }
    return ;
}

void InfiniteLight() {
	read(n);
	read(s);
	manacher();
	println(maxn);
	return ;
}