JOUER又来打牛客周赛了,这次的B题比赛时并没有ac,得了95分,一开始是运行超时,然后经过稍微优化后,确实是不超时了,变成了答案错误,哈哈,然后又调了10分钟,还是没出来,还以为是什么特殊情况.....废话少说,上题解。
题目描述
小红定义一个字符串是好串,当且仅当该字符串任意一对相邻字符都不同。
现在小红拿到了一个01串,请你帮小红求出有多少个长度不小于2的连续子串是好串。
输入描述:
一个长度不超过200000的字符串,仅由'0'和'1'组成。
输出描述:
输出相邻字符均不同的连续子串数量。
示例1
输入
01011
输出
6
说明
有2个"01"子串,1个"10"子串,1个"010"子串,1个"101"子串,1个"0101"子串。
思路:
这题是在一个01串中找到有多少长度大于等于2的连续子串(任意一对相邻字符都不同)
一开始的思路就是双重for循环,一个一个往后找,前一个字符和当前字符不相同,子串数加一。显然这样超时了,我们其实从第i个字符遍历到第j个字符时,i+1,i+2一直到j的子串数其实也是知道的,当不是子串后,就没必要回溯到i+1了,i+1到j的子串数其实就比i到j少1,少了(i,i+1),同理,i,i+1,i+2一直到j的子串数其实一个公差为1的等差数列,这样当不符合情况后直接i=j-1,节省了大量的时间。还有记得开long long,不然过不了。
代码:
#include <bits/stdc++.h>
#define ll long long
#define endl "\n"
using namespace std;
int main()
{
string s;
cin >> s;
ll ans = 0;//还有记得开long long!!!
ll a[s.size() + 5] = {0};
for (ll i = 0; i < s.size(); i++)
{
ll t = 0;
for (ll j = i + 1; j < s.size(); j++)
{
if (s[j] == s[j - 1])
{
ans += (1 * (t - 1) + (t - 2) * (t - 1) / 2);//等差数列求和
i = j - 1;
break;
}
else
{
t++;
ans++;
if (j == s.size() - 1)//防止没有(s[j] == s[j - 1])这种情况
{
ans += (1 * (t - 1) + (t - 2) * (t - 1) / 2);
i = j;
break;
}
}
}
}
cout << ans;
return 0;
}
大家有什么想法欢迎分享,我这种方法不是最优解,只是提供一种思路,万一对某人有帮助呢!jouer加油!