RT,思路就是用数组 c 记录每个形如TBTB..BTTB..TBTB中对于每个B,如果要将其变为 T,需要变换的 BTTB 中第一个 B 出现的位置,若左右两边均有 BTTB 则赋值为 −1,然后暴力 O(n) 查找最长的区间。
查找过程中,对于每个 i∈[l,r] 的区间:
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int n,T,now,ans,c[N];
bool a[N],b[N];
char s[N];
signed main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>T;while(T--){
cin>>n>>s;for(int i=0; i<=n; ++i)a[i]=b[i]=c[i]=0;
for(int i=0; i<n-1; ++i)if(s[i]=='T'&&s[i+1]=='B')a[i]=1;
for(int i=0; i<n-3; ++i)
if(s[i]=='B'&&s[i+1]=='T'&&s[i+2]=='T'&&s[i+3]=='B'){
b[i]=1;
if(c[i])c[i]=-1;else c[i]=i+1;
if(c[i+3])c[i+3]=-1;else c[i+3]=i+1;
}
for(int i=5; i<n; ++i){
if(s[i]=='B'&&c[i-2]&&a[i-1]){
if(c[i]&&c[i]!=c[i-2]){c[i]=-1;continue;}
c[i]=c[i-2];
}
}
for(int i=0; i<n-6; ++i)
if(s[i]=='B'&&c[i+2]&&a[i+1]){
if(c[i]&&c[i]!=c[i+2]){c[i]=-1;continue;}
c[i]=c[i+2];
}
for(int i=n; i>=1; --i)s[i]=s[i-1],c[i]=c[i-1];
ans=now=0;for(int l=0,r=1; r<=n; ++r){
if(s[r]=='T'){
int x=0;
if(c[l]&&(c[l]+3<=l||c[l]==-1))++x;
if(c[r+1]&&(r<c[r+1]||c[r+1]==-1))++x;
ans=max(ans,r-l+x);
}else l=r;
}
cout<<ans<<'\n';
}return 0;
}