Codeforces 1178B WOW Factor

题目简述

给定一个只含 \(\texttt{v}\)\(\texttt{o}\) 的字符串 \(s\),求字符串中有多少个 \(\texttt{wow}\)(一个 \(\texttt{w}\) 即为连续的两个 \(\texttt{v}\))。

题目分析

考虑枚举每一个 \(\texttt{o}\),设下标为 \(i\),统计它左边和右边各有多少个 \(\texttt{w}\),分别设为 \(a_{i-1}\)\(b_{i+1}\),依据乘法原理,将它们乘起来即为答案,累加即可。

接下来,考虑怎么处理右边出 \(\texttt{w}\) 的个数,\(a_i\) 表示区间 \([1,i]\) 中有多少个 \(\texttt{w}\),如果当前的 \(s_i=\texttt{o}\),那么则从 \(a_{i-1}\) 转移即可,如果当前 \(s_i=\texttt{v}\),那要分两种情况:

  • 如果 \(s_{i-1}=\texttt{o}\),那么就组合不成 \(\texttt{w}\),即 \(a_i \leftarrow a_{i-1}\)
  • 如果 \(s_{i-1}=\texttt{v}\),那么 \(s_i\) 就可以与 \(s_{i-1}\) 组合成一个 \(\texttt{w}\),即 \(a_i \leftarrow a_{i-1}+1\)

知道了左边怎么处理,右边也同理,反着做就可以了。

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define random(a,b) (rand()%(b-a+1)+a)
#define se second
#define fi first
#define pr pair<int,int>
#define pb push_back
#define ph push
#define ft front
#define For(i,a,b) for(int i=a;i<=b;i++)
#define Rep(i,a,b) for(int i=a;i>=b;i--)
#define mem(a,b) memset(a,b,sizeof a)
const int N=1e6+10;
char s[N];
int n;
ll a[N],b[N],ans;
int main()
{
	ios::sync_with_stdio(false);
    cin.tie(0);
    cin>>s+1;
    n=strlen(s+1);
    For(i,1,n) a[i]=a[i-1]+(s[i]=='v'&&s[i-1]=='v');
    Rep(i,n,1) b[i]=b[i+1]+(s[i]=='v'&&s[i+1]=='v');
    For(i,1,n)
    {
    	if(s[i]=='o')
    	{
    		ans+=(ll)a[i-1]*b[i+1];
		}
	}
	cout<<ans;
	return 0;
}
posted @ 2024-05-17 19:42  zhuluoan  阅读(13)  评论(0)    收藏  举报