贪心

考虑用连续的 $\texttt{A}$ 和 $\texttt{B}$ 把字符串切割成数个极长连续交替段,已知有四种类型的连续段,假设连续段长度为 $m$,下面是一些性质。

  • $\texttt{ABA} \cdots \texttt{ABA}$:拆分为一个 $\texttt{A}$ 和总共 $\left\lfloor \dfrac{m}{2} \right\rfloor$ 个 $\texttt{BA}$ 或 $\texttt{AB}$ 段。
  • $\texttt{BAB} \cdots \texttt{BAB}$:拆分为一个 $\texttt{B}$ 和总共 $\left\lfloor \dfrac{m}{2} \right\rfloor$ 个 $\texttt{BA}$ 或 $\texttt{AB}$ 段。
  • $\texttt{AB} \cdots \texttt{AB}$:可拆分得到 $\dfrac{m}{2}$ 个 $\texttt{AB}$ 或通过消耗一个 $\texttt{A}$ 和一个 $\texttt{B}$ 拆分为总共 $\dfrac{m}{2} - 1$ 个 $\texttt{BA}$ 或 $\texttt{AB}$ 段。
  • $\texttt{BA} \cdots \texttt{BA}$:可拆分得到 $\dfrac{m}{2}$ 个 $\texttt{BA}$ 或通过消耗一个 $\texttt{A}$ 和一个 $\texttt{B}$ 拆分为总共 $\dfrac{m}{2} - 1$ 个 $\texttt{BA}$ 或 $\texttt{AB}$ 段。

显然应该将字符串尽可能多地分割为 $\texttt{AB}$ 或者 $\texttt{BA}$ 段。为了减少损失,优先考虑 $\texttt{AB} \cdots \texttt{AB}$ 和 $\texttt{BA} \cdots \texttt{BA}$,尽量用无损手段完成匹配

更简单的理解:将 $\texttt{AB} \cdots \texttt{AB}$ 拆成仅含有 $\texttt{AB}$ 的段落比消耗一个 $\texttt{A}$ 和一个 $\texttt{B}$ 放的 $\texttt{AB}$ 更多,$\texttt{BA} \cdots \texttt{BA}$ 同理。要尽可能多地完成这样的拆分就应该优先拆分长度更短的段落

分割字符串后,优先考虑长度较小的 $\texttt{AB}$ 或者 $\texttt{BA}$ 段,能部分匹配就将其部分匹配,其余部分容易处理。时间复杂度 $O(|S| \log |S|)$。

#include<bits/stdc++.h>
using namespace std;
int n,a,b,ab,ba,las;
string c,s;
void solution(){
    cin>>s>>a>>b>>ab>>ba,c.clear(),n=s.size(),s='#'+s;
    c.push_back(s[1]);
    for(int i=2;i<=n-1;i++){
        if(s[i]!=s[i-1]||s[i]!=s[i+1]) c.push_back(s[i]);
        else s[i]=='A' ? --a:--b;
    }
    if(n!=1) c.push_back(s[n]);
    vector<int> aba,bab,abab,baba;
    las=1,s=c,n=s.size(),s='#'+s;
    s.push_back(s[n]);
    for(int i=2;i<=n+1;i++) if(s[i]==s[i-1]){
        if(s[i-1]=='A'&&s[las]=='A') aba.push_back((i-1)-las+1);
        if(s[i-1]=='B'&&s[las]=='B') bab.push_back((i-1)-las+1);
        if(s[i-1]=='B'&&s[las]=='A') abab.push_back((i-1)-las+1);
        if(s[i-1]=='A'&&s[las]=='B') baba.push_back((i-1)-las+1);
        las=i;
    }
    sort(aba.begin(),aba.end()),sort(bab.begin(),bab.end());
    sort(abab.begin(),abab.end()),sort(baba.begin(),baba.end());
    auto pa=abab.begin(),pb=baba.begin();
    while(pa!=abab.end()||pb!=baba.end()){
        static bool goa;
        if(pa!=abab.end()&&pb!=baba.end()) goa=(*pa<=*pb);
        else goa=(pb==baba.end());
        if(goa){
            int x=min(ab,*pa/2);
            ab-=x,*pa-=x*2;
            if(*pa!=0){
                --a,--b,*pa-=2;
                x=min(ba,*pa/2);
                ba-=x,*pa-=x*2;
            }
            if(*pa!=0) a-=*pa/2,b-=*pa/2;
            *pa=0,++pa;
        }
        else{
            int x=min(ba,*pb/2);
            ba-=x,*pb-=x*2;
            if(*pb!=0){
                --a,--b,*pb-=2;
                x=min(ab,*pb/2);
                ab-=x,*pb-=x*2;
            }
            if(*pb!=0) a-=*pb/2,b-=*pb/2;
            *pb=0,++pb;
        }
    }
    for(int &i:aba){
        --a,--i;
        int x=min(ab,i/2);
        ab-=x,i-=x*2;
        x=min(ba,i/2);
        ba-=x,i-=x*2;
        a-=i/2,b-=i/2,i=0;
    }
    for(int &i:bab){
        --b,--i;
        int x=min(ab,i/2);
        ab-=x,i-=x*2;
        x=min(ba,i/2);
        ba-=x,i-=x*2;
        a-=i/2,b-=i/2,i=0;
    }
    if(a>=0&&b>=0) cout<<"Yes"<<'\n';
    else cout<<"No"<<'\n';
}
int T;
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    cin>>T;
    while(T--) solution();
    return 0;
}
最后修改:2025 年 02 月 26 日
如果觉得我的文章对你有用,请随意赞赏