回文字符串
蓝桥杯2024省赛-回文字符串
题目描述
给定一个只包含小写字母的字符串 S,可以在字符串的开头加入任意数目的指定字符 l、q、b。问是否能通过这种方式将 S 转化为一个回文字符串。
输入格式
第一行一个整数 T,表示数据组数。
接下来 T 行,每行一个字符串 S。
输出格式
输出 T 行,每行 Yes 或 No。
样例
输入:
3
gmgqlq
pdlbll
aaa输出:
Yes
No
Yes解题思路
核心思想
只能在开头添加字符,新增字符必须与原串末尾的一段相对应。先统计开头连续的 l/q/b 个数 prefix,以及末尾连续的指定字符个数 suffix。全串都是指定字符时直接返回 Yes;否则 suffix 小于 prefix 时无解。
末尾保留 prefix 个字符,与原串开头配对;仅剥离末尾多出的 suffix-prefix 个字符,再判断留下的前缀是否回文。因为第一个和最后一个非指定字符的位置必须对称,需要剥离的数量是确定的。若剩余前缀为回文,在开头补上已剥离部分的逆序即可。
不能直接剥离整个末尾指定字符段:例如 lal 本来就是回文,应保留最后的 l。
不能在匹配完两端后继续跳过中间的不匹配字符,那相当于在原串内部插入字符。例如 alba 应输出 No。
双指针模拟
def check(s: str) -> bool:
# 全是指定字符时,可在开头补上逆序串
prefix = 0
while prefix < len(s) and s[prefix] in "lqb":
prefix += 1
if prefix == len(s):
return True
# 末尾必须保留 prefix 个字符,与原串开头配对
right = len(s) - 1
while right >= 0 and s[right] in "lqb":
right -= 1
suffix = len(s) - 1 - right
if suffix < prefix:
return False
right += prefix
left = 0
while left < right:
if s[left] != s[right]:
return False
left += 1
right -= 1
return True复杂度分析
- 时间复杂度:O(|S|),每组数据只需一次遍历
- 空间复杂度:O(1)
完整代码
import os
import sys
t = int(input())
def check(s: str) -> bool:
# 全是指定字符时,可在开头补上逆序串
prefix = 0
while prefix < len(s) and s[prefix] in "lqb":
prefix += 1
if prefix == len(s):
return True
# 末尾必须保留 prefix 个字符,与原串开头配对
right = len(s) - 1
while right >= 0 and s[right] in "lqb":
right -= 1
suffix = len(s) - 1 - right
if suffix < prefix:
return False
right += prefix
left = 0
while left < right:
if s[left] != s[right]:
return False
left += 1
right -= 1
return True
for _ in range(t):
s = input()
print('Yes' if check(s) else 'No')
样例解释
- gmgqlq:末尾指定字符段是 qlq,剩余 gmg 为回文;在开头补 qlq,得到 qlqgmgqlq ✅
- pdlbll:剥离末尾 lbll 后,剩余 pd 不是回文,返回 False ❌
- aaa:本身是回文 ✅