题目
题目描述
Farmer John 最近购入了 N 头新的奶牛(),每头奶牛的品种是更赛牛(Guernsey)或荷斯坦牛(Holstein)之一。
奶牛目前排成一排,Farmer John 想要为每个连续不少于三头奶牛的序列拍摄一张照片。 然而,他不想拍摄这样的照片,其中只有一头牛的品种是更赛牛,或者只有一头牛的品种是荷斯坦牛——他认为这头奇特的牛会感到孤立和不自然。 在为每个连续不少于三头奶牛的序列拍摄了一张照片后,他把所有「孤独的」照片,即其中只有一头更赛牛或荷斯坦奶牛的照片,都扔掉了。
给定奶牛的排列方式,请帮助 Farmer John 求出他会扔掉多少张孤独的照片。如果两张照片以不同的奶牛开始或结束,则认为它们是不同的。
输入格式
输入的第一行包含 N。
输入的第二行包含一个长为 N 的字符串。如果队伍中的第 i 头奶牛是更赛牛,则字符串的第 i 个字符为 G。否则,第 i 头奶牛是荷斯坦牛,该字符为 H。
输出格式
输出 Farmer John 会扔掉的孤独的照片数量。
样例
输入样例
5 GHGHG
输出样例
3
样例说明
这个例子中的每一个长为 3 的子串均恰好包含一头更赛牛或荷斯坦牛——所以这些子串表示孤独的照片,并会被 Farmer John 扔掉。 所有更长的子串(GHGH、HGHG 和 GHGHG)都可以被接受。
数据范围与提示
测试点 2-4 满足 N≤50。
测试点 5-10 满足 N≤5000。
为了增加一些挑战,测试点 11 没有额外限制。注意这个测试点的答案可能无法用标准的 32 位整数型存储,你可能需要使用更大的整数类型(例如,C++ 中 64 位的 "long long int" 类型)。
分析
接下来,我们开始分析这一道题
普通暴力
可以先固定左端点l,然后再不断延伸右端点r,统计区间[l,r]中有多少个是孤独的。这个算法的时间复杂度为,可以通过前10组数据。但最后一组数据无法通过。
#include <bits/stdc++.h>
using namespace std;
int n,ans,g,h;
string s;
int main(){
ios::sync_with_stdio(false);
cin>>n>>s;
for(int i=0;i<s.size();i++){
g=0,h=0;
for(int j=i;j<s.size();j++){
if(s[j]=='G')g++;
else h++;
if(g+h>=3&&(g==1||h==1))ans++;
}
}
cout<<ans<<endl;
return 0;
}
O(n)算法
代码如下:
#include<bits/stdc++.h>
using namespace std;
string s;
long long ans,n;
int main(){
ios::sync_with_stdio(false);
cin>>n>>s;
for(int i=0;i<n;i++){
long long le=0;
if (i>0&&s[i-1]!=s[i]){
le++;
for(int k=i-2;k>=0&&s[k]==s[i-1];k--){
le++;
}
}
long long ri=0;
if(i+1<n&&s[i+1]!=s[i]){
ri++;
for(int k=i+2;k<n&&s[k]==s[i+1];k++){
ri++;
}
}
ans+=le*ri+max(le-1,0LL)+max(ri-1,0LL);
}
cout<<ans<<endl;
return 0;
}