*完美的代价
问题描述
回文串,是一种特殊的字符串,它从左往右读和从右往左读是一样的。小龙龙认为回文串才是完美的。现在给你一个串,它不一定是回文的,请你计算最少的交换次数使得该串变成一个完美的回文串。
交换的定义是:交换两个相邻的字符
例如mamad
第一次交换 ad : mamda
第二次交换 md : madma
第三次交换 ma : madam (回文!完美!)
输入格式
第一行是一个整数N,表示接下来的字符串的长度(N <= 8000)
第二行是一个字符串,长度为N.只包含小写字母
输出格式
如果可能,输出最少的交换次数。
否则输出Impossible
首先,考虑Impossible的情况,当字符串中字母出现次数为奇数的字母数量大于1时,输出Impossible
随后,从左侧首个字母开始进行比较。选中左侧字母后,从右侧首个字母开始比较两个字母是否相同。等到两字母相同时,若字母位置对称则不需交换位置。反之则进行交换,并记录交换次数,以此类推。
若选中奇数字母,则计算其交换至中点位置的距离并记录。
最后将两部分交换次数求和并输出
图片来源:https://blog.csdn.net/qq_40605470/article/details/79268979
#include<iostream>
using namespace std;
int main()
{
int N=0,singular=0,cnt=0;
int chara[26] = {0};
cin >> N;
char s[N] = {0};
int j=N-1;
for(int i=0;i<N;i++)
cin >> s[i];
for(int i=0;i<N;i++)
chara[s[i]-'a']++;
for(int i=0;i<26;i++)
{
if(chara[i] % 2 != 0)
singular++;
}
if(singular > 1)
{
cout << "Impossible";
return 0;
}
else{
for(int i=0;i<(N+1)/2;i++)//i-左方指针
{
for(int k=j;k>=i;k--)//k-右方指针
{
if(s[i]==s[k])
{
if(i==k){
cnt += (N + 1) / 2 - i - 1;
break;
}
while(k<j){
swap(s[k],s[k+1]);
cnt++;
k++;
}
j--;
break;
}
}
}
}
cout << cnt;
return 0;
}