P3590 题解
题面
原题传送门
思路
由于这个帖子没有人给出 hack,所以我就照着这个思路开始证明。
结论:最终答案的左端点在 \(1\sim3\) 的位置之一或者右端点在 \(n-2\sim n\) 的位置之一。
假设目前的字符串 a1 a2 a3 res a4 a5 a6
,其中 \(res\) 为当前的最优解。
- \(res\) 中只有一个字符 \(ch\),则有两种情况。
- \(|ch|=1\),则 \(res\) 可以在 \(a_{1\sim6}\) 里任意一个,所以满足结论。
- \(|ch|>1\),则单独考虑
res a4
,若 \(a_4=ch\),则 \(res\) 可以扩展;若 \(a_4\neq ch\),则 \(|a_4|=1\),此时 \(|a_4|\neq|ch|\),所以在这种情况下,结论成立。
- \(res\) 中有多个字符,那么这三个字符的出现次数不一样,不妨设 \(|B|>|C|>|S|\),则又有三种情况。
- \(a_3=\)
B
或 \(a_4=\)B
,则 \(res\) 可以继续往外扩展。 - \(a_3=\)
C
或 \(a_4=\)C
,设 \(a_4=\)C
,若 \(res\) 可以扩展到 \(a_4\),则满足结论;若不能扩展到 \(a_4\),则有 \(|B|=|C|+1\),接下来考虑扩展 \(a_3,a_5\),若 \(a_3,a_5\) 中有一个为B
或C
,则可以扩展;若 \(a_3,a_5=\)S
,于是考虑a3 res
即S res
,若 \(res\) 可以扩展到 \(a_3\),则满足结论;若不能扩展,则有 \(|C|=|S|+1\),于是联立下前面的式子,\(res\) 里字母数量满足 \(|B|=|C|+1=|S|+2\)。继续讨论,若 \(a_2=\)B
,则a2 a3 res a4
即B S res C
满足题意;若 \(a_2=\)C
,则a2 a3 res a4
即C S res C
满足题意;若 \(a_2=\)S
,继续讨论 \(a_1\),若 \(a_1=\)B
,则a1 a2 a3 res
即B S S res
满足题意;若 \(a_1=\)S
,则a1 a2 a3 res
即S S S res
满足题意;若 \(a_1=\)C
,继续讨论 \(a_6\),若 \(a_6=\)B
,则res a4 a5 a6
即res C S B
满足题意;若 \(a_6=\)C
,则res a4 a5 a6
即res C S C
满足题意;若 \(a_6=\)S
,则a1 a2 a3 res a4 a5 a6
即C S S res C S S
满足题意。综上所述,当 \(a_4=\)C
时,\(res\) 可以扩展。 - \(a_3,a_4=\)
S
(一个为S
的情况上面已经讨论),若a3 res
和a3 res a4
都不能扩展,则有 \(|B|=|C|+1=|S|+2\),接下来考虑 \(a_2,a_5\),若 \(a_2,a_5=\)B
,则a2 a3 res a4
即C S res S
满足题意,\(a_5\) 同理也满足题意;若 \(a_2,a_5=\)S
,则a2 a3 res a4
即S S res S
满足题意,\(a_5\) 同理也满足题意;若 \(a_2,a_5=\)C
,继续考虑 \(a_1,a_6\),若 \(a_1,a_6=\)B
,则a1 a2 a3 res
即B C S res
满足题意,\(a_6\) 同理也满足题意;若 \(a_1,a_6=\)C
,则a1 a2 a3 res
即C C S res
满足题意,\(a_6\) 同理也满足题意;若 \(a_1,a_6=\)S
,则a1 a2 a3 res a4 a5 a6
即S C S res S C
满足题意,\(a_6\) 同理也满足题意。综上所述,\(a_3,a_4=\)S
时,\(res\) 可以扩展。
- \(a_3=\)
证毕,所以只要用前缀和记录下字符串字母出现的次数,一个个判断过去即可,时间复杂度为 \(O(n)\)。
代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define ll long long
using namespace std;
const int MN=1e6+5;
ll n,s[MN][3],ans=1;
char c[MN];
void write(ll n){if(n<0){putchar('-');write(-n);return;}if(n>9)write(n/10);putchar(n%10+'0');}
ll read(){ll 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;}
char gc(){char ch=getchar();while(ch!='B'&&ch!='C'&&ch!='S')ch=getchar();return ch;}
ll gs(char ch){if(ch=='C') return 0;if(ch=='B') return 1;return 2;}
int main(){n=read();for(int i=1; i<=n; i++){c[i]=gc();s[i][gs(c[i])]++;}for(int i=1; i<=n; i++) for(int j=0; j<3; j++) s[i][j]+=s[i-1][j];for(int i=1; i<=3; i++) for(int j=n; j>i; j--) if((s[j][0]-s[i-1][0]!=s[j][1]-s[i-1][1]&&s[j][1]-s[i-1][1]!=s[j][2]-s[i-1][2]&&s[j][0]-s[i-1][0]!=s[j][2]-s[i-1][2])||(s[j][0]-s[i-1][0]+s[j][1]-s[i-1][1]+s[j][2]-s[i-1][2]==s[j][0]-s[i-1][0])||(s[j][0]-s[i-1][0]+s[j][1]-s[i-1][1]+s[j][2]-s[i-1][2]==s[j][1]-s[i-1][1])||(s[j][0]-s[i-1][0]+s[j][1]-s[i-1][1]+s[j][2]-s[i-1][2]==s[j][2]-s[i-1][2])) ans=max(ans,(ll)j-i+1);for(int j=n; j>n-3; j--) for(int i=1; i<j; i++) if((s[j][0]-s[i-1][0]!=s[j][1]-s[i-1][1]&&s[j][1]-s[i-1][1]!=s[j][2]-s[i-1][2]&&s[j][0]-s[i-1][0]!=s[j][2]-s[i-1][2])||(s[j][0]-s[i-1][0]+s[j][1]-s[i-1][1]+s[j][2]-s[i-1][2]==s[j][0]-s[i-1][0])||(s[j][0]-s[i-1][0]+s[j][1]-s[i-1][1]+s[j][2]-s[i-1][2]==s[j][1]-s[i-1][1])||(s[j][0]-s[i-1][0]+s[j][1]-s[i-1][1]+s[j][2]-s[i-1][2]==s[j][2]-s[i-1][2])) ans=max(ans,(ll)j-i+1);write(ans);putchar('\n');return 0;
}