问题描述
回文串,是一种特殊的字符串,它从左往右读和从右往左读是一样的。小龙龙认为回文串才是完美的。现在给你一个串,它不一定是回文的,请你计算最少的交换次数使得该串变成一个完美的回文串。
交换的定义是:交换两个相邻的字符
例如 m a m a d mamad mamad
第一次交换 a d ad ad : m a m d a mamda mamda
第二次交换 m d md md : m a d m a madma madma
第三次交换 m a ma ma : m a d a m madam madam (回文!完美!)
输入格式
第一行是一个整数 N N N,表示接下来的字符串的长度( N N N <= 8000 8000 8000)
第二行是一个字符串,长度为 N N N.只包含小写字母
输出格式
如果可能,输出最少的交换次数。
否则输出 I m p o s s i b l e Impossible Impossible
样例输入
5
m a m a d mamad mamad
样例输出
3
个人思路:外层循环从头开始遍历( i = 0 i = 0 i=0 ~ j ( n − 1 ) j (n - 1) j(n−1)),内层循环从尾开始遍历到上层循环 i i i( k = j k = j k=j ~ k = i k = i k=i),若是找到相等的数( s [ i ] = = s [ k ] s[i] == s[k] s[i]==s[k]),则将后面的数移到回文数对应位置;如果( i = = k i == k i==k),说明有一个单个的数,则先判断个数如果为偶数,则说明不可能构成回文数,然后标记此次相等,若下一次再次出现 i = = k i == k i==k,则说明不可能构成回文数,因为说明有两个单个的数
/*
*两种情况判断不能形成回文数
* 1. 找到单个的数并且数为偶数个
* 2. 找到两个单个的数
*/
#include <iostream>
using namespace std;
int main() {
int n;
string s;
cin >> n >> s;
int flag = 0;
int count = 0;
int j = n - 1;
for (int i = 0; i < j; ++i) {
for (int k = j; k >= i; k--) {
if (i == k) {
//有单个的数并且总数为偶数个、或者已经有一个单个的数
if (n % 2 ==0 || flag) {
cout << "Impossible";
return 0;
}
//出现单个的数就标记,然后将该数移到中间
flag = 1;
count += n/2 - i;
}
//找到相等的数,把后面那个数移到回文数对应的位置
else if(s[i] == s[k]) {
for (int m = k; m < j; ++m) {
swap(s[m], s[m + 1]);
count++;
}
j--;
break;
}
}
}
cout << count;
return 0;
}