游戏机本当下手(字符串+尺取)
链接:https://ac.nowcoder.com/acm/contest/8755/E
来源:牛客网
藤原妹红拿到了一个游戏机,游戏机上有'1'和'0'两个按钮。
妹红发现,只要按住某个按钮不放,屏幕上就能一直不断打印那个字符。
比如对于"11111111100000000001111111111",只需要按住1、再按住0、再按住1就可以打印出来了。这样妹红最少只需要按3次按钮就可以打印这个字符串。
现在妹红拿到了一个01字符串,她想截取其中的一个子串,这个子串最少按
次按钮就可以打印出来。
(01字符串指仅由字符'0'和字符'1'组成的字符串)
注意这里“最少按
次”的含义是:按
次可以打印出这个子串,但按
次就一定打印不出这个子串。
妹红想知道,一共有多少子串符合要求?
注:一个字符串的子串为该字符串删掉前面和后面部分字符(也可以不删)生成的字符串。两个子串只要在字符串中位置不同则认为是不同的(哪怕字符串相等)。
输入描述:
第一行两个正整数
和
,分别代表字符串的长度、和妹红按下按钮的次数。
第二行为一个仅由字符“0”和“1”组成的字符串。
输出描述:
妹红至少按
次就能按出来的子串的数量。
示例1
说明
注意到k=2,因此要寻找最少按2次就能打印的子串。
s[0,2]="001",妹红最少按2次就能按出来,先按0再按1。
s[0,3]="0011",妹红最少按2次就能按出来,先按0再按1。
s[1,2]="01",妹红最少按2次就能按出来,先按0再按1。
s[0,3]="011",妹红最少按2次就能按出来,先按0再按1。
s[2,4]="110",妹红最少按2次就能按出来,先按1再按0。
s[2,5]="1100",妹红最少按2次就能按出来,先按1再按0。
s[3,4]="10",妹红最少按2次就能按出来,先按1再按0。
s[3,5]="100",妹红最少按2次就能按出来,先按1再按0。
共有8个子串符合要求。
示例2
备注:
对于20%的样例,
对于40%的样例,
对于60%的样例,
对于100%的样例,
这个题目不能直接进行尺取
要处理一下,把他变成没有连续的就可以进行尺取了,
尺取的权值就是ans+=a[l].sum*a[r].sum;
其中m=1的时候要特判
#include<iostream> #include<algorithm> using namespace std; typedef long long ll; const int maxn=1e6+100; struct node{ char num; ll sum; }a[maxn]; char str[maxn]; int main(){ int n,m; cin>>n>>m; scanf("%s",str+1); a[1].num=str[1]; a[1].sum=1; int cnt=1; for(int i=2;i<=n;i++){ if(str[i]==a[cnt].num){ a[cnt].sum++; } else{ cnt++; a[cnt].num=str[i]; a[cnt].sum=1; } } if(m==1){ ll ans=0; for(int i=1;i<=cnt;i++){ ans+=(a[i].sum*(a[i].sum+1))/2; } cout<<ans<<endl; return 0; } int l=1,r=0; int p=0; ll ans=0; while(1){ while(r<=cnt&&p<m){ r++; p++; } if(p<m){//要先判断break,在加权值 break; } ans+=1ll*a[l].sum*a[r].sum; p--; l++; } cout<<ans<<endl; }
其实这个没有必要尺取的
思路:先统计出每段1和0的个数,如果k等于1的话,那么对于每一段就是1 + 2 + 3 + ....,求和公式,否则就是i就是从第k项开始,看第i项与第i-k项乘起来,具体看代码
#include <iostream> #include <queue> using namespace std; typedef long long LL; LL n,k; int main() { string str; cin >> n >> k; cin >> str; vector<int>v; for(int i = 0;i < n;i ++){ int cnt = 0; int j = i; for(j = i;j < n;j ++){ if(str[j] == str[i]){ cnt ++; }else{ break; } } i = j - 1; v.push_back(cnt); } LL res = 0; if(k == 1){ for(auto &x : v){ res += 1ll*(x + 1)* x / 2; } }else{ k --; for(int i = k;i < v.size();i ++) { res += 1ll*v[i] * v[i - k] ; } } cout << res << endl; return 0; }