Steve的游戏名

题目链接

单点时限: 1.0 sec

内存限制: 128 MB

定义一个字符串s是一步字符串,当 s 满足以下两个条件:

  1. s 中仅包含小写字母。
  2. 对于任意的1≤i<|s|满足,s[i]+1=s[i+1],也就是说,s[i]在英文字母表中的位置的下一位是s[i+1],特别的,我们认为z的下一位是a,其中|s|表示s的长度。

举个例子:abc、zab 都是一步字符串,而 acd、zbc不是。

Steve 特别喜欢长长的名字,因此他在 Minecraft 中的名字特别特别的长。

Alex 对 Steve 的名字特别感兴趣,她想知道 Steve 的名字中有多少个子串是一步字符串

形式化来说,对于一个字符串 s,问有多少对 <i,j> 满足 1≤i≤j≤n,且 s[i]...s[j] 是一步字符串

保证 Steve 在 Minecraft 中的名字仅包含小写英文字母。

输入格式

输入包含多组测试数据。

第一行一个数字 T ,表示测试数据个数。

接下来每两行表示一个测试数据。

第一行一个数字 n 。

第二行一个长度为 n 的字符串 s。

数据范围:1≤T≤100,1≤n≤2⋅10^5

输出格式

一个数字表示答案。

样例

input

2
3
abc
3
zab

output

6
6

提示

abc中的一步字符串有abcabbcabc
zab中的一步字符串有zabzaabzab

题解:

题目分析:题意很容易就能理解,关键是如何计算子串的个数。

来看数据范围,抛去100组测试数据不说,你光是2*10^5暴力枚举两次,就爆了。

那么,换个角度去看问题吧。这道题其实是个思维题,也要找到规律。即使允许暴力,找到规律的做法也更为简洁,看来思维真是比懂的算法多重要啊。

首先分析样例,通过样例可以知道,a、b、c,单个任意字母为一个子串,两个、三个字母都可以成为子串,那4个也能成为子串了。像这样3个、4个以及更多的相连字符,你列举一下,很快就能发现规律,长度为n的一步字符串的子串个数为n*(n+1)/2。

来看个字符串                                  abchbcdaaacdbb

 所有一步字符串就是这样分布的    abc h bcd a a a cd b b

发现没,这些一步字符串可以分开来求,你只要设一个sum表示总数,每求到一个一步字符串,就累加它的子串个数就行了。

至于题上说的,z的下一位是a,这个可以最后考虑,加上一个限制条件就行了。

注意,最后结果是是long long类型,因为有多个累加。

AC代码:

#include <iostream>
#include <algorithm>
#include <vector>
#include <stdio.h>

using namespace std;

typedef long long ll;

int main()
{
//	freopen("input.txt","r",stdin); 
	std::ios::sync_with_stdio(false);
	
	int T;
	cin>>T;
	while(T--)
	{
		ll len;
		cin>>len;
		string str;
		cin>>str;
		ll length=1;
		ll sum=0;
		for(ll i=0;i<len;i++)
		{
			if(str[i]+1==str[i+1]||(str[i]=='z'&&str[i+1]=='a'))
			{
				length++;
			}
			else
			{
				sum+=length*(length+1)/2;
				length=1;
			}
		}
		cout<<sum<<endl;
	 } 
	
	return 0;
}

(--fxd)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值