问题描述
回文串,是一种特殊的字符串,它从左往右读和从右往左读是一样的。小龙龙认为回文串才是完美的。现在给你一个串,它不一定是回文的,请你计算最少的交换次数使得该串变成一个完美的回文串。
交换的定义是:交换两个相邻的字符
例如mamad
第一次交换 ad : mamda
第二次交换 md : madma
第三次交换 ma : madam (回文!完美!)
n<=8000
思路:
首先,对是否能构成回文串进行判定:
- 若每个字母出现次数均为偶数,则能构成
- 若有且仅有一个字母出现奇数次,则能构成
- 否则,不能构成
接下来对能构成回文串的串使用贪心策略:
- 为了防止重复,字母均采用从左至右单向交换
- 处理区间为[0,mid],每次遇到一个字母,就去从字符串结尾未归位的位置往前开始找对应字母,将其向后交换至回文对应位置
- 遇到出现奇数次的字母,且其查找到的字母位置与本字母位置相同,则先跳过此字母,将剩余字母处理完成之后,给总交换次数加上此字母交换至mid位置的交换次数,则得到答案
注:此代码由一组数据超时
n=0
ss=""
numCh=[0]*26
ans=0
def judge():
for i in ss:
numCh[ord(i)-ord('a')]+=1
# print(numCh)
odd_i=-1
odd_num=0
t_len=len(ss)
book=[0]*26
for i in range(t_len):
# if book[ord(ss[i])-ord('a')]==1:
# continue
if numCh[ord(ss[i])-ord('a')]%2==1:
if book[ord(ss[i])-ord('a')]!=1:
odd_num+=1
if odd_i==-1:
odd_i=i
elif abs(odd_i-t_len//2)>abs(i-t_len//2):
odd_i=i
book[ord(ss[i])-ord('a')]=1
if odd_num>1:
return False
elif odd_num==1:
global ans
return True
def myFind(x,t_i):
# t_i=len(ss)-1
while(t_i>=0 and ss[t_i]!=x):
t_i-=1
return t_i
n=int(input())
ss=list(input())
if not judge():
print("Impossible")
else:
t_len=len(ss)
midd=t_len//2
t_flag=t_len-1
if t_len%2==0:
midd-=1
i=0
t_midd=midd
while i<midd:
t_ptr=myFind(ss[i],t_flag)
if t_ptr==i:
t_midd=i
i+=1
continue
ans+=(t_flag-t_ptr)
t_flag-=1
for j in range(t_ptr,t_flag+1):
ss[j],ss[j+1]=ss[j+1],ss[j]
i+=1
ans+=(midd-t_midd)
print(ans)