题目
问题描述
给定一段仅由大写字母组成且长度为
n
n
n的字符串,我们将一个至少包含
k
k
k个字母
R
R
R且不含字母
P
P
P的连续的字符串视为一种合法方案,问总共有多少种合法方案。
分析
由于合法方案中是不含字母 P P P的,所以我们可以以 P P P作为分割点进行分割字符串,我们以 l , r l,r l,r作为分割出的字符串的左右边界,接下来的问题就是求在这个字符串中有多少个子字符串至少包含 k k k个 R R R。
我们可以采用双指针来解决问题
i
i
i作为左端点,
j
j
j作为右端点
inline void f(){
int i,j,cnt=0;
for(i=j=l+1;i<r;i++){
while(j<r&&cnt<k){
cnt+=(s[j]=='R');
j++;
}
if(cnt==k)ans+=(r-j+1);
if(s[i]=='R')cnt--;
}
l=r;
}
需要注意的是,当 r = n + 1 r=n+1 r=n+1时,仍然要进行讨论,不要漏了。
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5+10;
char s[N];
ll a[N],ans,n,k,l,r;
inline void f(){
int i,j,cnt=0;
for(i=j=l+1;i<r;i++){
while(j<r&&cnt<k){
cnt+=(s[j]=='R');
j++;
}
if(cnt==k)ans+=(r-j+1);
if(s[i]=='R')cnt--;
}
l=r;
}
int main(){
cin>>n>>k>>s+1;
for(r=1;r<=n;r++){
if(s[r]=='P')f();
}
f();
cout<<ans<<endl;
}
另外一种更简洁的写法,
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
string s;
ll n,k,ans;
int main(){
cin>>n>>k;
cin>>s;
int cnt=0;
for (int i=0,j=0,l=0;i<n;i++){
while (cnt<k&&j<=n){
if(j<n){
cnt+=(s[j]=='R');
}
j++;
}
if (l<i){//处理'P'连续的情况
l=i;
}
while(l<n&&s[l]!='P'){
l++;
}
cnt-=(s[i]=='R');
ans+=max(0,l-j+1);
}
cout<<ans<<endl;
return 0;
}