孤独的照片

来自Y总的寒假每日一题中的第一题,作为一个算法大白,从最基础的角度解释一下我对此题理解,欢迎任何批评指正!

首先上题目

Farmer John 最近购入了 N 头新的奶牛,每头奶牛的品种是更赛牛(Guernsey)或荷斯坦牛(Holstein)之一。

奶牛目前排成一排,Farmer John 想要为每个连续不少于三头奶牛的序列拍摄一张照片。

然而,他不想拍摄这样的照片,其中只有一头牛的品种是更赛牛,或者只有一头牛的品种是荷斯坦牛——他认为这头奇特的牛会感到孤立和不自然。

在为每个连续不少于三头奶牛的序列拍摄了一张照片后,他把所有「孤独的」照片,即其中只有一头更赛牛或荷斯坦奶牛的照片,都扔掉了。

给定奶牛的排列方式,请帮助 Farmer John 求出他会扔掉多少张孤独的照片。

如果两张照片以不同位置的奶牛开始或结束,则认为它们是不同的。

输入格式
输入的第一行包含 N。

输入的第二行包含一个长为 N 的字符串。如果队伍中的第 i 头奶牛是更赛牛,则字符串的第 i 个字符为 G。否则,第 i头奶牛是荷斯坦牛,该字符为 H。

输出格式
输出 Farmer John 会扔掉的孤独的照片数量。

数据范围
3≤N≤5×105
输入样例:
5
GHGHG
输出样例
3
样例解释
这个例子中的每一个长为 3 的子串均恰好包含一头更赛牛或荷斯坦牛——所以这些子串表示孤独的照片,并会被 Farmer John 扔掉。

所有更长的子串(GHGH、HGHG 和 GHGHG)都可以被接受。

题目大致意思就是说给你一个字符串,然后你需要找出一个子串(这子串包含连续三个及以上的字符,其中只包含一个单独的字母,比如只包含一个G,其他都是H)

解题思路

  1. 首先从前至后枚举字符串中的每一个字符,找到它左边与它不同连续字符的最大数;再从后至前枚举字符串中的每一个字符,找到它右边与它不同的连续字符的最大数;最后将这两个最大数相乘。这里必须要说明,只要左边有一个,右边有一个字符和中间字符不一样,就可以构成一个连续三个其中一个和其他两个不一样的子串,所以左边再多几个,右边再多几个,均可构成连续三个以上孤独的子串,利用乘法原理得出最终结果。
  2. 当左边没有字符,也就是那个孤独的字符是第一个字符时,我们只需要考虑它右边的情况,那么右边就需要至少有两个字符,就是我们在步骤一中右边找到的最大数-1;当右边没有字符,也就是那个孤独的字符是最后一个字符时,我们只需要考虑它左边的情况,那么左边就需要至少两个字符,也是左边找到的最大数-1。
  3. 最后结果就是把三种情况得到的数加起来。

代码如下

#include
#include
#include
using namespace std;
typedef long long LL;

const int N=500010;

int n;
char str[N];
int l[N],r[N];
int main(){
	cin>>n>>str;
	
	for(int i=0,h=0,g=0;i<n;i++)
		if(str[i]=='G') l[i]=h,h=0,g++;
		else l[i]=g,g=0,h++;
	
	for(int i=n-1,h=0,g=0;i>=0;i--)
		if(str[i]=='G') r[i]=h,h=0,g++;
		else r[i]=g,g=0,h++;
		
	LL res=0;
	for(int i=0;i<n;i++)
		res+=(LL)l[i]*r[i]+max(l[i]-1,0)+max(r[i]-1,0);
		
	cout<<res<<endl;
	return 0; 
} 

你可能感兴趣的:(Acwing寒假每日一题,算法,c++)