Codeforces 1178E. Archaeology

传送门

首先一定有解,考虑归纳法证明

首先 $n<=3$ 时显然

考虑 $n=4$ 时,那么因为 $s[1]!=s[2],s[3]!=s[4]$ ,并且 $s[i] \in {a,b,c}$ 由鸽巢原理显然意味着 $s[1],s[2]$ 至少有一个等于 $s[3]$ 或 $s[4]$

那么我们从中间往两边延伸,每左边两个就和右边两个组合,这样每四个位置就有两个位置会贡献回文字符,那么一定有解

注意如果 $n \mod 4=2$ 或者 $n \mod 4=3$ 时最后会剩下几个不能组成左边两个右边两个,那么我们回文长度搞成奇数即可(中间先选择一个作为回文中心)

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
using namespace std;
typedef long long ll;
inline int read()
{
    int x=0,f=1; char ch=getchar();
    while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
    while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
    return x*f;
}
const int N=2e6+7;
int n;
char s[N];
vector <int> ans;
void work(int l,int r)
{
    for(; l>=2&&r<=n-1; l-=2,r+=2)
    {
        vector <int> cnt[3];
        cnt[s[l-1]-'a'].push_back(l-1);
        cnt[s[r+1]-'a'].push_back(r+1);
        cnt[s[l]-'a'].push_back(l);
        cnt[s[r]-'a'].push_back(r);
        for(int k=0;k<3;k++)
            if(cnt[k].size()>1)
            {
                ans.push_back(cnt[k][0]),
                ans.push_back(cnt[k][1]);
                break;
            }
    }
}
int main()
{
    scanf("%s",s+1); n=strlen(s+1);
    int mid=1+n>>1;
    if(n%4) { ans.push_back(mid); work(mid-1,mid+1); }
    else work(mid,mid+1);
    sort(ans.begin(),ans.end());
    for(auto p: ans) printf("%c",s[p]);
    puts(""); return 0;
}

猜你喜欢

转载自www.cnblogs.com/LLTYYC/p/11612640.html