为了更好的阅读体检,可以查看我的算法学习网
在线评测链接:P1492
题目内容
塔子哥对于一个字符串的权值定义为一个字符串中 "tzzt"
的子串的数量。例如,"tzzt"
的权值为
1
1
1,"tzztzzt"
的权值为
2
2
2,"tzzzt"
的权值为
0
0
0 。
现在,塔子哥给你一个仅由 't'
和 'z'
构成的字符串,问你这个字符串的所有子串的权值之和。
输入描述
第一行,一个只由 't'
和 z
构成的字符串
字符串长度不超过 2 × 1 0 5 2\times 10^5 2×105
输出描述
一个整数,表示这个字符串的所有子串的权值之和。
样例
输入
tzztzzt
输出
8
说明
s[1,4]="tzzt"
,权值为
1
1
1
s[1,5]="tzztz"
,权值为
1
1
1
s[1,6]="tzztzz"
,权值为
1
1
1
s[1,7]="tzztzzt"
,权值为
2
2
2
s[2,7]="zztzzt"
,权值为
1
1
1
s[3,7]="ztzzt"
,权值为
1
1
1
s[4,7]="tzzt"
,权值为
1
1
1
权值之和为 8 8 8
思路: 思维
考虑字符串中每个 tzzt
对答案的贡献。
下标从
0
0
0 开始。假设是 s[i, i+3] = "tzzt"
,那么这个 tzzt
对于答案的贡献为:所有
l
<
=
i
,
r
>
=
i
+
3
l <= i, r >= i+3
l<=i,r>=i+3 的字符串。
这样的字符串一共有 ( l + 1 ) × ( n − r ) (l+1) \times (n-r) (l+1)×(n−r) 个。
累加起来即可。
时间复杂度: O ( n ) O(n) O(n)
代码
#include <bits/stdc++.h>
using namespace std;
int main()
{
string s;
cin >> s;
int n = int(s.size());
long long ans = 0;
for (int i = 0; i + 4 < n; ++i) {
if (s.substr(i, 4) == "tzzt") {
// 当前这个串可以在多少个子串中贡献权值
// 左边界和右边界
int l = i + 1;
int r = n - 1 - (i + 3) + 1;
ans += 1ll * l * r;
}
}
cout << ans << "\n";
return 0;
}