A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

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

思路:先判断这个字符串是否可以组成一个回文字符串,然后按照每一个字母出现的次数为偶数还是奇数进行讨论。每一次都是从第一个字母开始往后进行检测,要是遇到了出现次数为1的字母,先不要动它,等到其他的字母都排完了,再直接将其放到字符串的中间即可;如果所有的字母出现次数都为偶数个,那么从字符串的最后开始往前检测,直到遇到和当前字母相同的字母,再进行位置交换。

复制代码
  1 #include<iostream>
  2 using namespace std;
  3
  4 class huiwen
  5 {
  6 public:
  7     int get_n()
  8     {
  9         cin>>n;
10         return n;
11     }
12     void get_putin()
13     {
14         cin>>putin;
15     }
16     void exchange()
17     {
18         for(int i=0;i<n;i++)
19         {
20             num[putin[i]-'a']++;
21         }
22         for(int i=0;i<26;i++)
23         {
24             if(num[i]%2!=0)
25             {
26                 t++;
27             }
28         }
29         if(t>=2)  //要是有两个或两个以上的字母出现次数为奇数,那么这个字符串不可能为回文字符串
30         {
31             cout<<"Impossible";
32             return;
33         }
34         else if(t==0)    //说明所有字母的出现次数都是偶数
35         {
36             for(int i=0;i<n/2-1;i++)
37             {
38                 flag=-1;
39                 for(int j=n-a-1;j>i;j--)
40                 {
41                     if(putin[i]==putin[j])
42                     {
43                         flag=j;
44                         break;
45                     }
46                 }
47                 char temp=putin[flag];
48                 for(int m=flag;m<n-1-a;m++)
49                 {
50                     putin[m]=putin[m+1];
51                 }
52                 putin[n-1-a]=temp;
53                 time=time+(n-1-a-flag);   //计算移动次数
54                 a++;
55             }
56         }
57         else if(t==1)
58         {
59             for(int i=0;i<=n/2;i++)
60             {
61                 flag=-1;
62                 for(int j=n-a-1;j>i;j--)
63                 {
64                     if(putin[i]==putin[j])
65                     {
66                         flag=j;
67                         break;
68                     }
69                 }
70                 if(flag==-1)   //遇到出现次数为1次的字母了
71                 {
72                     time=time+(n/2-i);
73                 }
74                 else
75                 {
76                     char temp=putin[flag];
77                     for (int m = flag; m < n - 1 - a; m++)
78                     {
79                         putin[m] = putin[m + 1];
80                     }
81                     putin[n - 1 - a] = temp;
82                     time = time + (n - 1 - a - flag);   //计算移动次数
83                     a++;
84                 }
85             }
86         }
87         cout<<time;
88         return;
89     }
90 private:
91     int n;    //输入字符串所含字母个数
92     char putin[8001];   //输入字符串
93     int num[26]={0};   //一共有26个字母,判断每一个字母的出现次数
94     int t=0;   //整个字符串里面有多少个出现次数为奇数的字母
95     int a=0;   //表示已经处理到第a个字母
96     int flag;  //用flag来记录后一半字符串匹配的最近的字母下标
97     int time=0;  //用来计算移动字母的次数
98 };
99
100 int main(void)
101 {
102     huiwen string;
103     string.get_n();
104     string.get_putin();
105     string.exchange();
106     return 0;
107 }
复制代码
注意:题目中的交换的意思和一般的交换意思不一样,这里只能挨个地进行交换,而一般所说的交换是直接将两个字符进行对调,所以计算交换次数的时候不能只算一次。

1 个回复

倒序浏览
更多讯息欢迎添加小优:DKA-2018
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马