http://acm.hdu.edu.cn/showproblem.php?pid=5340
题意
判断是否能将字符串S分成三段非空回文串
分析
manacher预处理出前缀和后缀回文的位置, 枚举第一个回文串和第三个回文串,这样得到第二个回文串的区间,找中点,因为manacher处理后所有的回文串长度都是奇数,然后根据中点的回文半径判断中间部分是否回文即可, 复杂度o(n2)。至于n2复杂度为什么能水过去。。不是很懂
#include<iostream>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
#include<cstdio>
#include<algorithm>
#include<map>
#include<set>
#define rep(i,e) for(int i=0;i<(e);i++)
#define rep1(i,e) for(int i=1;i<=(e);i++)
#define repx(i,x,e) for(int i=(x);i<=(e);i++)
#define X first
#define Y second
#define PB push_back
#define MP make_pair
#define mset(var,val) memset(var,val,sizeof(var))
#define scd(a) scanf("%d",&a)
#define scdd(a,b) scanf("%d%d",&a,&b)
#define scddd(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define pd(a) printf("%d\n",a)
#define scl(a) scanf("%lld",&a)
#define scll(a,b) scanf("%lld%lld",&a,&b)
#define sclll(a,b,c) scanf("%lld%lld%lld",&a,&b,&c)
#define IOS ios::sync_with_stdio(false);cin.tie(0) using namespace std;
typedef long long ll;
template <class T>
void test(T a){cout<<a<<endl;}
template <class T,class T2>
void test(T a,T2 b){cout<<a<<" "<<b<<endl;}
template <class T,class T2,class T3>
void test(T a,T2 b,T3 c){cout<<a<<" "<<b<<" "<<c<<endl;}
const int N = 1e6+;
//const int MAXN = 210;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3fll;
const ll mod = ;
int T;
void testcase(){
printf("Case #%d: ",++T);
}
const int MAXN = 4e4+;
const int MAXM = ;
char ma[MAXN],s[MAXN];
int mp[MAXN];
int pre[MAXN],suf[MAXN];
void Manacher(int len){
int l=;
ma[l++]='$';
ma[l++]='#';
for(int i=;i<len;i++) ma[l++]=s[i],ma[l++]='#';
ma[l]=;
int mx=,id=;
for(int i=;i<l;i++){
mp[i]=mx>i?min(mp[*id-i],mx-i):;
while(ma[i+mp[i]]==ma[i-mp[i]]) mp[i]++;
if(i+mp[i]>mx){
mx=i+mp[i];
id=i;
}
}
}
int main() {
#ifdef LOCAL
freopen("in.txt","r",stdin);
#endif // LOCAL
int t;
scd(t);
while(t--){
scanf("%s",s);
int len = strlen(s);
Manacher(len);
int l=,r=;
len=*len+;
for(int i=;i<=len;i++){
if(mp[i]==i&&i!=) pre[l++]=mp[i];
//mp[i]==i保证mp[i]可以作为第一个回文串的半径,加入pre数组,i!=1保证第一个回文串不为空
if(mp[i]+i-==len&&i!=len) suf[r++]=mp[i];
}
int i,j;
for(i=l-;i>=;i--){
for(j=;j<r;j++){
int t1=*pre[i];
int t2=len+-*suf[j];
int tmp = (t1+t2)>>;
if(t1>t2) continue;
if(mp[tmp]==) continue;
if(mp[tmp]*->=t2-t1+) break;
}
if(j<r) break;
}
if(i>=) puts("Yes");
else puts("No");
}
return ;
}