考虑使用贪心求解。
首先,统计 LGR 和 CSP 的数量。对数量小的进行拆解。我用一个变量 k 表示出现次数少的子串的数量。如果只出现了其中一种,那么就对那一种做操作就好了。如果都没有出现,输出 0。
因为每次可以交换两个字符,所以每次都能用交换的方式破坏两个 LGR(或 CSP)子串。答案就是 \(\left\lceil\dfrac{k}{2}\right\rceil\)。
向上取整的原因
假设有这样一组样例:CSPCSPCSPLGRLGRLGRLGRLGR。
用一次交换破坏两个 CSP 字串之后,变成这样(交换方式不唯一):CPSCPSCSPLGRLGRLGRLGRLGR。
如上,还有一个 CSP 没有被拆掉。所以还需要一次把剩下的 CSP 拆掉。答案即为 \(\left\lceil\dfrac{3}{2}\right\rceil = 2\)。
AC 代码
#include<bits/stdc++.h>
using namespace std;
int main(){
int q;
scanf("%d",&q);
while(q--){
string s;
cin >> s;
if(s.find("LGR")==string::npos||s.find("CSP")==string::npos){//都没有出现,输出 0。
printf("0\n");
}else{
int lgr=0,csp=0;//分别统计 LGR 和 CSP 的数量。
for(int i=2; i<s.size(); i++){
if(s[i]=='R'&&s[i-1]=='G'&&s[i-2]=='L'){
lgr++;
// printf("%d ",i);
}
if(s[i]=='P'&&s[i-1]=='S'&&s[i-2]=='C'){
csp++;
// printf("%d ",i);
}
}
int k=min(lgr,csp);//k 存储了 LGR 和 CSP 出现次数少的子串的数量。
int ans=ceil(1.0*k/2);//对 k 除以 2 向上取整,就是答案。
printf("%d\n",ans);
}
}
return 0;
}
浙公网安备 33010602011771号