[国家集训队]最长双回文串
题意是 求字符串 A +B = C 且 C 在序列中 A 和 B 都是回文串
运用了回文字符串优美的性质:删掉任意两个相同的字符仍然回文且长度减2
看到这题之后 我在想 如果把 A 字符串的末尾 设为 A 的长度 B 字符串的开始 设为 B 的长度
然后 设 A 字符串的 右端点 代表的长度为 \(R_i\)
设 B 字符串的 左端点 代表的长度为 \(L_i\)
然后 求 \(max\)\({L_i + R_i}\)
但是你会发现这样是不会得到最优解的 就像这样
aaaaa
答案是5 但是你只更新了 \(L_5\) 和 \(R_1\) 的值 所以程序认为的答案不是5 是 0
这样你就要开始递推
其实你统计的信息都是在分隔符上…然后你会发现两个分隔符里有一个字符
所以你 递推式 是 \(L_i\) =max{ \(L_i\) , \(L_{i+2} - 2\)} \(R_i\) = max{\(R_i\) , \(R_{i-2}-2\)}
然后再取 \(max\)\({L_i+R_i}\)
#include<bits/stdc++.h>
using namespace std ;
#define int long long
#define fi first
#define se second
#define pb emplace_back
inline int read() {
register char c = getchar() ;
register int x = 0 , f = 1 ;
for( ; ! isdigit(c) ; c = getchar()) if(c == '-') f = -1 ;
for( ; isdigit(c) ; c = getchar()) x = (x << 1) + (x << 3) + (c & 15) ;
return x * f ;
}
template < typename T > inline bool cmax(T & x , T y) {
return x < y ? x = y , 1 : 0 ;
}
template < typename T > inline bool cmin(T & x , T y) {
return x > y ? x = y , 1 : 0 ;
}
inline int QP(int x , int y , int Mod) { int ans = 1 ;
for( ; y ; y >>= 1 , x = (x * x) % Mod)
if(y & 1) ans = (ans * x) % Mod ;
return ans ;
}
const int N = 2e5 + 10 ;
char s[N] , fix[N << 1] ;
int p[N << 1] ;
int L[N << 1] , R[N << 1] ;
signed main() {
scanf("%s" , s + 1) ;
int n = strlen(s + 1) ;
int len = 0 ;
fix[++ len] = '$' ;
fix[++ len] = '%' ;
for(register int i = 1 ; i <= n ; i ++)
fix[++ len] = s[i] , fix[++ len] = '%' ;
int mid = 0 , id = 0 ;
for(register int i = 1 ; i <= len ; i ++) {
if(i <= id) p[i] = min(p[(mid << 1) - i] , id - i + 1) ;
while(fix[i - p[i]] == fix[i + p[i]]) p[i] ++ ;
if(i + p[i] > id) mid = i , id = i + p[i] - 1 ;
cmax(L[i + p[i] - 1] , p[i] - 1) ;
cmax(R[i - p[i] + 1] , p[i] - 1) ;
} int ans = 0 ;
for(register int i = 2 ; i <= len ; i += 2) cmax(R[i] , R[i - 2] - 2) ;
for(register int i = len ; i >= 1 ; i -= 2) cmax(L[i] , L[i + 2] - 2) ;
int QWQ = 2333 ;
for(register int i = 1 ; i <= len ; i ++) (L[i] && R[i]) ? cmax(ans , L[i] + R[i]) : QWQ;
printf("%lld\n" , ans) ;
return 0 ;
}