1. 问题描述:
农夫约翰的农场布局十分奇特,一条大型的环形道路将奶牛吃草的田地围了起来。每天早晨,奶牛们穿过这条道路,进入到田地吃草;每天晚上,奶牛们穿过这条道路,离开田地,返回牛棚休息。众所周知,奶牛是有习性的动物,每头奶牛每天通过道路的方式都相同。每头奶牛每天固定地从道路的某一位置进入田地,从道路的另一不同位置离开田地。所有奶牛的所有进出位置之间互不相同。约翰共有 26 头奶牛,依次命名为 A∼Z。因此,道路上共有 52 个不同的进出位置。约翰沿着环形道路按顺时针方向扫描了每个位置,并记录了每个位置处经过的奶牛的名字,最终形成了一个包含 52 个字母的序列,A∼Z 中的每个字母恰好出现两次。他并没有记录哪些位置是入口,哪些位置是出口。看着地图上记录的这些位置,约翰想要知道一天当中,有多少对奶牛之间的从入口穿过田地到达出口的路径可能会存在交叉。如果奶牛 A 从入口穿过田地到达出口的路径必须穿过奶牛 B 从入口穿过田地到达出口的路径,那么称这对牛 (A,B) 是"交叉"对。请帮助约翰计算"交叉"对(不考虑顺序,即 (A,B) 与 (B,A) 视为同一对 )的总数。
输入格式
共一行,包含一个长度为 52 的只包含大写字母的字符串,其中每个字母恰好出现两次。
输出格式
输出交叉对的总数。
输入样例:
ABCCABDDEEFFGGHHIIJJKKLLMMNNOOPPQQRRSSTTUUVVWWXXYYZZ
输出样例:
1
样例解释
在此样例中,只有 A 和 B 一对交叉对。
来源:https://www.acwing.com/problem/content/description/1791/
2. 思路分析:
分析题目可以知道我们可以枚举所有的两个字母组合的情况,总共有C26 2 = 325种情况,所以问题就转化为如何判断当前枚举的两个字母是否存在交叉,通过画图可以发现当前一个字母分居在另外两个相同字母的中间的时候存在交叉,所以我们可以先存储下每一个字母出现的两个位置,然后枚举所有可能的情况,判断是否满足条件即可。
3. 代码如下:
class Solution:
def process(self):
s = input()
p = [list() for i in range(26)]
for i in range(len(s)):
c = s[i]
# 这样同个字母出现的位置一定是递增的
p[ord(c) - ord("A")].append(i)
res = 0
# 因为AB与BA看成是同一种情况所以只需要枚举其中一种情况即可所以从i + 1开始枚举
for i in range(26):
for j in range(i + 1, 26):
count = 0
for y in p[j]:
# 只要是在当前字母的中间那么就计数
if p[i][0] < y < p[i][1]: count += 1
# 判断是否只有一个字母在当前字母p[i]的中间
if count == 1:
res += 1
return res
if __name__ == '__main__':
print(Solution().process())