Educational Codeforces Round 74 D.AB-string(思维+找规律)

题目描述

The string t1t2…tk is good if each letter of this string belongs to at least one palindrome of length greater than 1.
A palindrome is a string that reads the same backward as forward. For example, the strings A, BAB, ABBA, BAABBBAAB are palindromes, but the strings AB, ABBBAA, BBBA are not.
Here are some examples of good strings:
t = AABBB (letters t1, t2 belong to palindrome t1…t2 and letters t3, t4, t5 belong to palindrome t3…t5);
t = ABAA (letters t1, t2, t3 belong to palindrome t1…t3 and letter t4 belongs to palindrome t3…t4);
t = AAAAA (all letters belong to palindrome t1…t5);
You are given a string s of length n, consisting of only letters A and B.
You have to calculate the number of good substrings of string s.

Input

The first line contains one integer n (1≤n≤3⋅105) — the length of the string s.
The second line contains the string s, consisting of letters A and B.

Output

Print one integer — the number of good substrings of string s.

Examples

Input
5
AABBB
Output
6
Input
3
AAA
Output
3
Input
7
AAABABB
Output
15

Note

In the first test case there are six good substrings: s1…s2, s1…s4, s1…s5, s3…s4, s3…s5 and s4…s5.
In the second test case there are three good substrings: s1…s2, s1…s3 and s2…s3.

题目大意

给你一个只含有A和B的字符串s。如果一个字符串中的每一个字符都被包含在了一些长度大于1的回文子串中,那么这个字符串是一个好串。问:s中有多少个子串为好串。

题目分析

因为s的子串中好串的数量是要大于非好串的数量的,所以我们是不是可以只找出s中所有的非好串的子串,最后用总的子串减去非好串的子串。
进而我又发现:一个字符串如果是非好串,那么它的结构一定是一堆A+一个B或者一堆B+一个A(例如:AAAAAB)。
然后问题就比较简单了,先找出所有连续的字母并记录其长度a[i],然后算出s的所有子串的数量num=n(n-1)/2。然后每次让num减去a[i]+a[i+1]-1即可。
以AABBB为例:
AABBB可以分割为AA(长度为2)、BBB(长度为3)。s的总子串num=10。
s中的非好串可以分为一堆A+一个B和一堆B+一个A。
一堆A+一个B:AB、AAAB(2个)
一堆B+一个A:AB、ABB、ABBB(3个)
一个是2+3-一个重复的AB=4个。
答案即为6。

代码如下
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <stack>
#include <map>
#include <queue>
#include <vector>
#include <set>
#include <algorithm>
#include <iomanip>
#define LL long long
#define PII pair<int,int>
using namespace std;
const int N=2e5+5;
vector<int> a;
int main()
{
	int n;
	string s;
	cin>>n>>s;
	for(int i=0;i<n;i++)
	{
		char c=s[i];
		int cnt=1;			//记录相同字母的子串的长度
		while(s[i+1]==c)
		{
			i++;
			cnt++;
		}
		a.push_back(cnt);
	}
	LL ans=(LL)n*(n-1)/2;			//s的所有子串数
	for(int i=1;i<a.size();i++)
	{
		ans-=a[i-1]+a[i]-1;			//减去非好串的子串数
	}
	cout<<ans<<endl;
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lwz_159

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值