Codeforces 1178E Archaeology (鸽巢原理)

题意:

给你1e6的字符串,保证只含'a''b''c'三种字符,且相邻两个字符一定不一样

求一个大于等于n/2的回文子序列

思路:

朴素的最长回文子序列是n方的区间dp,这题显然不行,要充分利用题中所给的条件

我们发现,在任意不相交的两个区间[l,l+1]与[r,r+1]中

有两组相邻的字母,一共四个字母,而题目保证了每组两个相邻的字母肯定不同,

所以这四个字母中最多有3种字母,又因为每组字母不相同,所以这两个区间中一定有一个相同的字母

这题就搞完了

代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
//#include<cmath>
#include<cstring>
#include<string>
#include<stack>
#include<queue>
#include<deque>
#include<set>
#include<vector>
#include<map>
    
#define fst first
#define sc second
#define pb push_back
#define mem(a,b) memset(a,b,sizeof(a))
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lc root<<1
#define rc root<<1|1

using namespace std;

typedef double db;
typedef long double ldb;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> PI;
typedef pair<ll,ll> PLL;

const db eps = 1e-6;
const int mod = 998244353;
const int maxn = 2e6+100;
const int maxm = 2e6+100;
const int inf = 0x3f3f3f3f;
//const db pi = acos(-1.0);


int n;
char a[maxn];
int vis[maxn];
int main(){
    scanf("%s",a+1);
    n=strlen(a+1);
    int l=1,r=n;
    int ans = 0;
    while(l<=r){
        //printf("%d %d
",l,r);
        if(l==r){vis[l]=1;break;}
        if(l+1==r){vis[l]=1;break;}
        if(l+2==r){vis[l]=1;break;}
        if(a[l]==a[r]){vis[l]=vis[r]=1;}
        else if(a[l]==a[r-1]){vis[l]=vis[r-1]=1;}
        else if(a[l+1]==a[r-1]){vis[l+1]=vis[r-1]=1;}
        else if(a[l+1]==a[r]){vis[l+1]=vis[r]=1;}
        l+=2;r-=2;
    }
    for(int i = 1; i <= n; i++){
        if(vis[i])printf("%c",a[i]);
    }
    return 0;
}
/*
abcba
bcb
cb
aba
ababc
baba
cbacb
 */
原文地址:https://www.cnblogs.com/wrjlinkkkkkk/p/11221398.html