1. 问题描述:
奶牛贝茜在她最喜欢的牧场中发现了一块石碑,上面刻有神秘的碑文。碑文的文字似乎来自一种神秘的古代语言,可看作一个只包含 C,O,W 三种字符的字符串。尽管贝茜无法解密该文字,但是她很欣赏 C,O,W 按顺序构成她最喜欢的单词 COW。她想知道 COW 在碑文中一共出现了多少次。她不介意 C,O,W 之间是否存在其他字符,只要这三个字符按正确的顺序出现即可。她也不介意多个不同的 COW 是否共享了一些字符。例如,COW 在 CWOW 中只出现一次,在 CCOW 中出现两次,在 CCOOWW 中出现八次。给定碑文中的文字,请帮助贝茜计算 COW 出现的次数。
输入格式
第一行包含 N。第二行包含一个长度为 N 的字符串,其中只包含字符 C,O,W。
输出格式
输出给定字符串中 COW 作为子序列(不一定连续)的出现次数。
数据范围
1 ≤ N ≤ 10 ^ 5
输入样例:
6
COOWWW
输出样例:
6
来源:https://www.acwing.com/problem/content/description/1886/
2. 思路分析:
这道题目可以使用状态机dp来解决,我们可以定义两维的f,其中f(i,j)表示走完第i个字符,且走到状态j的方案数目,由题目可知第二维总共三种状态,分别表示以"C","O","W"结尾的三种状态,如何进行递推呢?可以按照是否包含s[i]划分为两大类进行递推,例如当s[i] == "C"中 f(i,0) = f(i - 1,0) + 1,如果不包含s[i],说明为f(i - 1,0),如果包含s[i]说明从只能够从起始状态到当前的字符s[i]为一种,所以f(i,0) = f(i - 1,0) + 1,而对于f(i,1) = f(i - 1,1),f(i,2) = f(i - 1,2)说明只能够从前i - 1个字符到达状态0,当s[i] == "O"时说明f(i,1) = f(i - 1,1) + f(i - 1,0)说明可以接在字符"C"的后面,对于其余状态的递推也是类似的,并且进一步可以发现当前状态只与前一个状态有关所以可以使用三个变量进行递推即可:
3. 代码如下:
class Solution:
def process(self):
n = int(input())
s = input()
# 因为当前状态只与前一个状态有关所以使用三个变量代替列表进行递推
a = b = c = 0
for i in range(n):
if s[i] == "C":
a += 1
# 接在"C"的后面
elif s[i] == "O":
b += a
elif s[i] == "W":
# 接在"CO"的后面
c += b
return c
if __name__ == "__main__":
print(Solution().process())