水贪心题

题目描述:

回文串,是一种特殊的字符串,它从左往右读和从右往左读是一样的。小龙龙认为回文串才是完美的。现在给你一个串,它不一定是回文的,请你计算最少的交换次数使得该串变成一个完美的回文串。
  交换的定义是:交换两个相邻的字符
  例如mamad
  第一次交换 ad : mamda
  第二次交换 md : madma
  第三次交换 ma : madam (回文!完美!)

如果可能,输出最少的交换次数。
否则输出Impossible

思路:

(一看到回文串,本来以为要用马拉车算法,结果发现这个是一个找规律的题)

(偶数情况)具体来说先找到从右面开始的第一个和当前枚举的字母一样的字母,把它的位置调整到与当前字母一样的位置,然后枚举下一个字母就行,直到枚举到一半即可,若中间有字母出现奇数次那么就表明当前字符串不可能构成回文串就输出Impossible

(奇数情况)除了某个奇数字母外其他情况和偶数情况一样的,都是逐个匹配,再交换,如果遇到奇数字母,那么先把它假定已经放到了中间,先把后面的字母处理完毕后,再把这个字母移到中间即可,若枚举的时候出现了两个奇数次字母那么就说明当前字符串不可以形成回文串输出Impossible

具体情况看code:

#include <iostream>
using namespace std;
int main(){
    ios::sync_with_stdio(false);
    int n;
    cin>>n;
    string s;
    cin>>s;
    int res=0,odd=0;
    for(int i=0,j=n-1;i<n/2;i++){
        int pos=j;
        while(s[i]!=s[j]&&j>i){
            j--;
        }
        if(j==i){
            //这里是判断是否可以组成回文串
            //如果说n为偶数那么不可能出现奇数次字母
            //如果说n为奇数那么就不会出现两次奇数字母
            if(n%2==0||odd==1){
                cout<<"Impossible"<<endl;
                return 0;
            }
            odd++;
            res+=(n/2-j);//这里是先假定把这个奇数次的字母先放到中间先处理后面的字母把后面的都调整为回文的时候再把这个字母移到中间就可以了
            j=pos;
            continue;
        }
        char tem=s[j];
        while(j<pos){
            s[j]=s[j+1];
            res++;
            j++;
        }
        //这里进行的是交换操作
        s[j]=tem;
        j--;
    }
    cout<<res<<endl;
}

猜你喜欢

转载自www.cnblogs.com/kstranger/p/12425976.html