原题链接:PTA | 程序设计类实验辅助教学平台
参考资料:
前缀和数组是一种数据结构,它存储了数组中某个位置之前的所有元素的和(在这个问题中,我们存储的是 'P' 和 'T' 的数量)。通过前缀和数组,我们可以在常数时间内获取到数组中任意位置之前的元素和(或数量),从而避免了重复计算,大大提高了算法的效率。
具体来说,我给出的优化方案通过以下步骤实现:
遍历字符串,构建两个前缀和数组
count_p
和count_t
,分别记录每个位置之前 'P' 和 'T' 的数量。再次遍历字符串,对于每个 'A',通过前缀和数组快速获取其左边 'P' 的数量和右边 'T' 的数量(通过总数量减去当前位置之前的数量)。
将左边 'P' 的数量和右边 'T' 的数量相乘,得到以当前 'A' 为中心的 "PAT" 子串的数量,并累加到总和中。
输出最终的总和,并对 MOD 取模以防止整数溢出。
这种方法的时间复杂度是 O(n),其中 n 是字符串的长度,因为我们只遍历了字符串两次(一次构建前缀和数组,一次计算 "PAT" 数量)。与原始方法相比,这种方法显著降低了时间复杂度,因为它避免了在每次遇到 'A' 时都重新计算 'P' 和 'T' 的数量。
Tips:以下Python代码仅个人理解,非最优算法,仅供参考!多学习其他大佬的AC代码!
MOD = 1000000007
s = input()
n = len(s)
# 计算前缀和数组,记录每个位置之前的'P'和'T'的数量
count_p = [0] * (n + 1)
count_t = [0] * (n + 1)
for i in range(1, n + 1):
if s[i - 1] == 'P':
count_p[i] = count_p[i - 1] + 1
else:
count_p[i] = count_p[i - 1]
if s[i - 1] == 'T':
count_t[i] = count_t[i - 1] + 1
else:
count_t[i] = count_t[i - 1]
# 遍历字符串,当遇到'A'时,计算以当前'A'为中心的PAT数量
sum_pat = 0
for i in range(n):
if s[i] == 'A':
# 左边'P'的数量乘以右边'T'的数量
left_p = count_p[i]
right_t = count_t[n] - count_t[i]
sum_pat = (sum_pat + left_p * right_t) % MOD
print(sum_pat)
'''15 / 25分,测试点2-4超时
s = input()
sum = 0
count_p = count_t = 0
for i in range(len(s)):
if s[i] == 'A':
count_p = s[:i].count('P')
count_t = s[i:].count('T')
sum += (count_p * count_t) % 1000000007
print(sum % 1000000007)
'''