描述
小红有一个 nn 颗宝石构成的环形宝石手串,即第一颗和最后一颗宝石相连,其中第 i个宝石的属性为 si ;若两个宝石的属性相同,那么这两个宝石会相互排斥,导致断开。
小红可以从手串中摘掉一些宝石,每次摘掉后,这个宝石左右的两个宝石会相接,手串依旧是环形。
小红想要破坏这个手串。她想要知道,最少还需要摘掉多少个宝石才会导致手串断开。特别的,当手串上剩余的宝石数量恰好为 2 而依旧没能
输入描述:
每个测试文件均包含多组测试数据。第一行输入一个整数 T(1≦T≦100)代表数据组数,每组测试数据描述如下:
第一行输入一个整数 n(2≦n≦105)代表手串初始的宝石数量。
第二行输入一个长度为 n 、仅由小写字母构成的字符串,代表手串上每个宝石的属性。
除此之外,保证单个测试文件的 n 之和不超过 105 。
断开时,视为破坏失败,直接输出 −1 。
输出描述:
对于每一组测试数据,如果手环无法破坏,直接输出 −1 ;否则,在一行上输出一个整数,代表手串断开需要的最少操作次数。
解答
#本质在于删除字符,使得相同字符之间的距离尽可能小
def main():
T = int(input())#测试组数
for _ in range(T):#遍历每个测试用例
n = int(input())#手串初始的宝石数量
s = input().strip()#手串上每个宝石的属性
len_s = len(s)
vet = [[] for _ in range(26)]#给每个字母创建一个数组存储其下标位置
#遍历字符串的每个属性,将其下标存入数组
for i in range(len_s):
vet[ord(s[i])-ord('a')].append(i)
#初始化最小操作数
ans = 99999
#遍历每个字母
for j in range(26):
#如果出现的次数是0或1,跳过
if len(vet[j])==0 or len(vet[j])==1:
continue
l = vet[j][0]#字母在字符最左边出现的位置
r = vet[j][-1]#字母在字符最右边出现的位置
ans = min(ans,r-l-1)#去除中间所有字符的最小操作次数
ans = min(ans,len_s-(r-l+1))#去除两端所有字符的最小操作次数
#进一步遍历看是否还有更近的距离
for k in range(1,len(vet[j])):
l = vet[j][k-1]
r = vet[j][k]
ans = min(ans,r-l-1)
if ans == 99999:
print(-1)
else:
print(ans)
main()