CF1178B题解
CF1178B题解
思路:前缀和+后缀和+乘法原理
首先建立两个数组:\(a\),\(b\),\(a\) 用来记录第 \(i\) 个字符前面有几个“vv”, \(b\) 用来记录第 \(i\) 个字符后面有几个“vv”。
那就很明了,用两个循环解决!如果第 \(i\) 个字符是 \(v\),第 \(i-1\)(\(i+1\))个也是,那前(后)缀就加 \(1\)。
接下来求出来了前后缀,到了重点部分:累加答案。
其实也挺简单的,就是再把整个字符串重新遍历一遍,要是找到一个 \(o\)(设这个 \(o\) 在字符串的第 \(i\) 个位置),则答案 \(ans\) 就加 \(a[i]\times b[i]\)。
这时有人就会问为啥加的是 \(a[i]\times b[i]\)?
这就要涉及小学的加乘原理了,这里用的是乘法原理:
前面有 \(a[i]\) 对,后面有 \(b[i]\) 对,总共就有 \(a[i]\times b[i]\) 对。
总结
- 开
long long,不开long long见祖宗。 - 前后缀和。
- 乘法原理。
代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
string s;
long long a[1000005],b[1000005],ans;
//a数组记录前缀和:前面有几个"vv"。
//b数组记录后缀和:后面有几个"vv"。
int main(){
cin>>s;
int len=s.size();
for(int i=1; i<len; i++){//记录前缀。
if(s[i]=='v'&&s[i-1]=='v') a[i]++;//多了一对"vv"。
a[i]+=a[i-1];
}
for(int i=len-1; i>=1; i--){//记录后缀。
if(s[i]=='v'&&s[i+1]=='v') b[i]++;//多了一对"vv"。
b[i]+=b[i+1];
}
for(int i=0; i<len; i++)//最后一次遍历求答案,找o,然后用乘法原理累加答案。
if(s[i]=='o')//找到一个o
ans+=b[i]*a[i];
//乘法原理。
//前面有a[i]对,后面有b[i]对,总共就有a[i]*b[i]对。
printf("%lld",ans);
return 0;
}

浙公网安备 33010602011771号