试题 基础练习 完美的代价

 一.题目

题目链接
  http://lx.lanqiao.cn/problem.page?gpid=T60
问题描述
  回文串,是一种特殊的字符串,它从左往右读和从右往左读是一样的。小龙龙认为回文串才是完美的。现在给你一个串,它不一定是回文的,请你计算最少的交换次数使得该串变成一个完美的回文串。
  交换的定义是:交换两个相邻的字符
  例如mamad
  第一次交换 ad : mamda
  第二次交换 md : madma
  第三次交换 ma : madam (回文!完美!)
输入格式
  第一行是一个整数N,表示接下来的字符串的长度(N <= 8000)
  第二行是一个字符串,长度为N.只包含小写字母
输出格式
  如果可能,输出最少的交换次数。
  否则输出Impossible
样例输入
5
mamad
样例输出
3

二.解决

思路:交换的定义是交换两个相邻的字符!最后交换成功的结果是两边字母对称。

问题:什么字符串一定不可能成为回文串?

字符串有大于等于2种的字母个数为奇数    也即:回文串只能最多有一种字母其个数为奇数,其余都应为偶数

以下是建立在该字符串一定为回文串的处理方法

从前向后遍历字符串,对每一个字符找到与该字符相同字符的位置,因为要使得移动次数最少,所以可以从后往前遍历字符串,找到第一个与它相等的字符,并且移动到对称的位置,统计移动的次数。

从左边往右边走  i = 0 to “对称位置”    i初始位置为0,对称位置为最右边,也即n-1      i++

从右边往左边走  j = “对称位置” to i+1  找到第一个与a[i]值(字母)相同的j   然后去移动  使得i的对称位置的字母为a[j]  总移动次数+=这里移动的次数 “对称位置”也往左移动一位(“对称位置”--

最后,我们要考虑一个问题,也即如果遇到个数只有一个的字母时我们应该要做的事情,我们要确保它在中间位置,个数只有一个的字母判断条件:当遍历完右边后都没有字母与它相等,这时j==i(也即遍历到了自身),我们需要将这个字母移动到中间,只需将总移动次数+=(N/2-i),不需要真正将它移动,因为在后面的寻找对称字母过程中,可能会将“这中间字母”又移动到其他地方,白做功夫,所以我们暂时先不移动它,等到所有的寻找过程完成之后,再对它进行移动(当然我们其实并不需要真的去移动它,因为我们已经知道移动次数:中间位置N/2-当前位置i)。

#include<bits/stdc++.h>
using namespace std;
#define maxn 8005
int mp[30];
int main(){
    int N,sum=0,k,i,j,flag=0,flag1=0;
    string s;
    cin>>N;
    cin>>s;
    memset(mp,0,sizeof(mp));
    //判断字符串能否成为回文串 
    for(int i=0;i<N;i++){
        mp[s[i]-'a']++;
    } 
    for(int i=0;i<24;i++){
        if(mp[i]%2==1)    flag1++;
        if(flag1>1)    break;
    } 
    if(flag1>1) printf("Impossible
");
    else{
    int temp=N-1;
    for(i=0;i<temp;i++){//从前向后找 
        for(j=temp;j>i;j--){//从后向前找 
            if(s[i]==s[j]){//遇到相等的字母则需要交换到合适的地方
             //从j位置移动到与i对称的位置(即temp)
             for(k=j;k<temp;k++){
                 s[k]=s[k+1];
             } 
            s[temp]=s[i];//也即之前的s[j],但s[j]已经被其他字母占了,所以用与它值相等的s[i]表示 
            sum+=temp-j;//这次移动的次数
            temp--;//缩小边界
            break; 
            }
        }
        if(j==i){//也即之前的“从后向前找”找不到相等的字母,只有自身,则将它移动到中间 
            sum+=(N/2 - i);
        }
    }
    cout<<sum<<endl;
    }
}
原文地址:https://www.cnblogs.com/Aiahtwo/p/12738229.html