Codeforces Global Round 7

D2 - Prefix-Suffix Palindrome (Hard version)

題意

S滿TSTabT=prea+sufb 給你一個字符串S,找出最長的滿足以下條件的字符串T:\\ 長度不超過|S|\\ T爲迴文字符串\\ 存在兩個字符串a和b(可能爲空),T=pre_a+suf_b

思路

+manacher預處理 + manacher
若s串首尾字符相同,那麼我們可以直接去除不影響答案。
故先從兩邊取對稱的前後綴,之後再取餘下字符串較長的迴文前綴或後綴。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int>P;
const double eps = 1e-8;
const int NINF = 0xc0c0c0c0;
const int INF  = 0x3f3f3f3f;
const ll  mod  = 1e9 + 7;
const ll  maxn = 3e6 + 5;

char s[maxn],a[maxn],b[maxn];
int p[maxn];
int ansid;

void manacher(int n){
	int m=0,mx=0,id=0;
	s[++m]='$';
	s[++m]='#';
	for(int i=1;i<=n;i++){
		s[++m]=a[i];
		s[++m]='#';
	}
	s[++m]='%';
	ansid=0;
	for(int i=3;i<m;i++){
		p[i]=mx>i?min(p[id*2-i],mx-i):1;
		while(s[i+p[i]]==s[i-p[i]]) ++p[i];
		if(i+p[i]>mx) mx=i+p[i],id=i;
		if(i+p[i]-1>=2*n+1 || i-p[i]+1<=3){//如果爲前綴和後綴那邊所在的最大回文串則記錄ansid以便於後續輸出
			if(p[i]>p[ansid]) ansid=i;
		}
	}
	for(int i=ansid-p[ansid]+1;i<=ansid+p[ansid]-1;i++){
		if(isalpha(s[i])) cout<<s[i];
	}
}

int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	int T;cin>>T;
	while(T--){
		cin>>b+1;
		int L=1,R=strlen(b+1),len=0;
		while(len+1<=R/2 && b[L+len]==b[R-len]) len++;
		for(int i=1;i<=len;i++) cout<<b[i];
		int cnt=0;
		for(int i=len+1;i<=R-len;i++) a[++cnt]=b[i];
		manacher(cnt);
		for(int i=len;i>=1;i--) cout<<b[i];cout<<'\n';
	}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章