📅  最后修改于: 2023-12-03 15:21:27.021000             🧑  作者: Mango
给定一个由小写字母a,b,c和大写字母Q组成的字符串s。你可以最多更改字符串中的三个字符。你需要将s转换为t,使得t没有回文子字符串(一个字符串是回文,当且仅当该字符串与其反转后的字符串相同)。还有一些查询Q,对于每个查询,你需要输出当前t中匹配查询的子字符串数量。
首先,我们先将所有的回文子字符串都找出来,并放到列表中。然后,对于每个回文子字符串,我们可以删除其中一个字符,以避免它是回文的。由于最多可以更改三个字符,因此我们现在可以删除最多三个回文子字符串中的一个字符。我们可以预处理回文子字符串的需要删除的字符数量,并使用动态规划算法找到可以删除的最少字符数。
假设我们有一个数组dp[i][j]
,它表示从i到j所需的最少字符数。当s[i] == s[j]时,如果从i + 1到j - 1所需的最少字符数小于等于1,那么dp[i][j] = dp[i + 1][j - 1]。否则,我们需要删除s[i]或s[j],因此dp[i][j] = 1 + min(dp[i + 1][j], dp[i][j - 1])。
最终的答案是字符串长度减去可以删除的最少字符数。
如此一来,我们就可以回答查询。我们可以使用哈希表来记录t中出现的多少次字符串。对于每个查询,我们只需要在哈希表中查找该子字符串出现的次数即可。
下面是一份Python代码,用于实现上述算法。
def count_palindromes(s):
n = len(s)
p = [[False] * n for _ in range(n)]
for i in range(n):
p[i][i] = True
for i in range(n - 1):
p[i][i + 1] = (s[i] == s[i + 1])
for l in range(2, n):
for i in range(n - l):
j = i + l
p[i][j] = p[i + 1][j - 1] and s[i] == s[j]
dp = [[float('inf')] * n for _ in range(n)]
for i in range(n):
dp[i][i] = 0
for i in range(n - 1):
dp[i][i + 1] = 1 if s[i] != s[i + 1] else 0
for l in range(2, n):
for i in range(n - l):
j = i + l
if s[i] == s[j]:
dp[i][j] = dp[i + 1][j - 1]
else:
dp[i][j] = 1 + min(dp[i + 1][j], dp[i][j - 1])
ans = n - min(dp[0][n - 1], 3)
counts = {}
for i in range(n):
for j in range(i + 1, n + 1):
if p[i][j - 1]:
t = s[i:j]
if t in counts:
counts[t] += 1
else:
counts[t] = 1
return ans, counts
s = input()
t, counts = count_palindromes(s.replace('Q', ''))
for _ in range(int(input())):
q = input()
if q in counts:
print(counts[q])
else:
print(0)