小红拿到了一个长度为 nnn 的字符串,该字符串仅由大写字母组成。
小红很喜欢红色(用'R'字母表示),但她非常讨厌紫色(用'P'字母表示)。
她想取一个连续子串,该子串包含至少 kkk 个'R'字符,且不能包含'P'字符。
你能告诉她有多少合法的方案可以取到吗?
注:只要连续子串的起始位置或终止位置不同,我们就认为是两个不同的方案。
输入描述:
第一行输入两个正整数 nnn 和 kkk ,用空格隔开。
输入一行字符串,该字符串保证仅包含大写字母('A'到'Z')。
数据范围:
1≤n≤2000001\leq n \leq 2000001≤n≤200000
1≤k≤201\leq k \leq 201≤k≤20
输出描述:
取一个连续子串,包含至少 k 个'R'字符、且不包含'P'字符的方案数。
示例1
输入
13 3 RRRPBRRRDBRPR
输出
10
说明
共有 10 个合法的子串选择方式。假设下标是从 0 到 12 ,那么 10 个合法串分别是:
s[0,2]s[0,2]s[0,2] = "RRR"
s[4,7]s[4,7]s[4,7] = "BRRR"
s[4,8]s[4,8]s[4,8] = "BRRRD"
s[4,9]s[4,9]s[4,9] = "BRRRDB"
s[4,10]s[4,10]s[4,10] = "BRRRDBR"
s[5,7]s[5,7]s[5,7] = "RRR"
s[5,8]s[5,8]s[5,8] = "RRRD"
s[5,9]s[5,9]s[5,9] = "RRRDB"
s[5,10]s[5,10]s[5,10] = "RRRDBR"
s[6,10]s[6,10]s[6,10] = "RRDBR"
这些串均含有不小于 3 个字符 'R',且不包含字符 'P'
示例2
输入
5 1 RARPR
输出
6
思路:这个题是让求组合数(PS:很少见组合数是用排列组合写的)。这个题是求子串的合法个数(子串是先处理出来的),见到子串合法:我们可以想双指针,因为是子串我们不让右指针r在最后即可(最右),然后再让左指针收缩即可。
总结:用双指针枚举极限,看看在当且仅当有k个的情况下能够位移多少距离来判断增加多少组合种类,始终让右端满足k个的条件。
完整代码:
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int mod=1e9+7;
const int N=2e5+10;
string s;
int n,k;
string t;
int gao(string t)
{
int res=0;
int j=0,temp=0;
for(int i=0;i<t.size();i++)
{
temp+=t[i]=='R';//后方更新,不断变长,j又能接着重新算了
while(j<=i&&temp>=k)
{
temp-=t[j++]=='R';
}
res+=j;
}
return res;
}
signed main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cin>>n>>k;
cin>>s;
s=" "+s;
int ans=0;
for(int i=1;i<=n;i++)
{
if(s[i]=='P')
{
ans+=gao(t);
t="";
}
else
{
t+=s[i];
}
}
ans+=gao(t);
cout<<ans<<endl;
return 0;
}