‘abb’ 型子序列
leafee 最近爱上了 abb 型语句,比如“叠词词”、“恶心心”
leafee 拿到了一个只含有小写字母的字符串,她想知道有多少个 “abb” 型的子序列?
定义: abb 型字符串满足以下条件:
字符串长度为 3 。字符串后两位相同。字符串前两位不同。
输入描述:
第一行一个正整数
第二行一个长度为 的字符串(只包含小写字母) 1≤≤1e5
输出描述:
“abb” 型的子序列个数。
示例1
输入
6
abcbcc
输出
8
说明
共有1个abb,3个acc,4个bcc
示例2
输入
4
abbb
输出
3
a
,在后缀中寻找 bb
(a, b, b)
,其中 a
是第一个字符,b
是后两个字符,且 a != b
。suf[i][c]
表示从位置 i
开始到字符串末尾,字符 c
的出现次数。a
:
i
,假设 s[i]
是 a
。i+1
开始)寻找字符 b
,且 b
至少出现两次。b
,则累加组合数 C(k, 2)
,其中 k
是字符 b
在后缀中的出现次数。b
在后缀中出现 k
次,符合条件的 bb
组合数为 k * (k - 1) // 2
。n = int(input())
s = [ord(x) - ord('a') for x in input()]
ans = 0
# 后缀和数组,suf[i][c] 表示从位置i到末尾字符c的出现次数
suf = [[0] * 26 for _ in range(n + 1)]
for i in range(n - 1, -1, -1):
for c in range(26):
suf[i][c] = suf[i + 1][c]
suf[i][s[i]] += 1
for i in range(n):
for j in range(26):
if j != s[i] and suf[i + 1][j] >= 2:
ans += suf[i + 1][j] * (suf[i + 1][j] - 1) // 2
print(ans)
后缀和数组的构建:O(n * 26)
。
枚举第一个字符并计算组合数:O(n * 26)
。
总时间复杂度:O(n * 26)
。
b
,分别在前缀中找 a
,后缀中找 b
(a, b, b)
,其中 b
是中间字符,a
是左边字符,且 a != b
。pre[i][c]
表示前 i
个字符中字符 c
的出现次数。suf[i][c]
表示从位置 i
开始到末尾,字符 c
的出现次数。b
:
j
,假设 s[j]
是 b
。j
个字符)寻找字符 a
,且 a != b
。j+1
开始)寻找字符 b
。a
的数量乘以右边 b
的数量。b
,累加 left * right
到答案中。n = int(input())
s = [ord(x) - ord('a') for x in input()]
# 前缀和数组:pre[i][c]表示前i个字符中字符c的出现次数
pre = [[0] * 26 for _ in range(n + 1)]
for i in range(n):
for c in range(26):
pre[i + 1][c] = pre[i][c]
pre[i + 1][s[i]] += 1
# 后缀和数组:suf[i][c]表示从位置i到末尾字符c的出现次数
suf = [[0] * 26 for _ in range(n + 2)]
for i in range(n - 1, -1, -1):
for c in range(26):
suf[i][c] = suf[i + 1][c]
suf[i][s[i]] += 1
ans = 0
for i in range(n):
# 左边不等于s[i]的字符数
left = sum(pre[i][c] for c in range(26) if c != s[i])
# 右边等于s[i]的字符数
right = suf[i + 1][s[i]]
ans += left * right
print(ans)
前缀和数组的构建:O(n * 26)
。
后缀和数组的构建:O(n * 26)
。
枚举中间字符并计算结果:O(n * 26)
。
总时间复杂度:O(n * 26)
。
a
,然后在后缀中寻找 bb
。b
,然后分别在前缀中找 a
,后缀中找 b
。(a, b, b)
的组合。O(n * 26)
,性能相近。END
如果有更多问题或需要进一步的帮助,可以在评论区留言讨论哦!
如果喜欢的话,请给博主点个关注 谢谢