题目描述
题目大意
给出一个只含有’a’、'b’或’c’的相邻字符不同的字符串s,求一个长度≥|s| div 2的回文子序列t
正解
这题的正解很妙
任意选两组相邻的两个字符,那么这两组中一定有相同的字符
因为一组中字符不能相同,所以一组选了两个不同的,另一组不能选出另外两个不同的(只有三种字符)
那么可以把s串从两侧向中间收缩,每次左右各取两个字符,这两个组一定有一个相同的字符
如此来构回文串,最后还剩字符的话就加进去回文的中心
这样构出的回文长度为
⌊
∣
s
∣
2
⌋
+
[
∣
s
∣
m
o
d
  
4
>
0
]
−
[
∣
s
∣
m
o
d
  
4
>
1
]
\left \lfloor \frac{\left | s \right |}{2} \right \rfloor +[\left | s \right | mod \;4>0]-[\left | s \right | mod \;4>1]
⌊2∣s∣⌋+[∣s∣mod4>0]−[∣s∣mod4>1]
题目要求的长度为
⌊
∣
s
∣
2
⌋
\left \lfloor \frac{\left | s \right |}{2} \right \rfloor
⌊2∣s∣⌋
显然是合法的
code
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
using namespace std;
int a[1000001];
int ans[500001];
int len,i,j,k,l,r,tot;
char ch;
int main()
{
// freopen("e.in","r",stdin);
ch=getchar();
while (ch>='a' && ch<='c')
{
a[++len]=ch-'a';
ch=getchar();
}
l=1;
r=len;
while (l+1<r-1)
{
if (a[l]==a[r-1])
ans[++tot]=a[l];
else
if (a[l+1]==a[r-1])
ans[++tot]=a[l+1];
else
if (a[l]==a[r])
ans[++tot]=a[l];
else
if (a[l+1]==a[r])
ans[++tot]=a[l+1];
l+=2;
r-=2;
}
fo(i,1,tot)
printf("%c",ans[i]+'a');
if (l<=r)
printf("%c",a[l]+'a');
fd(i,tot,1)
printf("%c",ans[i]+'a');
}