用C++实现:完美的代价

问题描述
  回文串,是一种特殊的字符串,它从左往右读和从右往左读是一样的。小龙龙认为回文串才是完美的。现在给你一个串,它不一定是回文的,请你计算最少的交换次数使得该串变成一个完美的回文串。
  交换的定义是:交换两个相邻的字符
  例如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 }

注意:题目中的交换的意思和一般的交换意思不一样,这里只能挨个地进行交换,而一般所说的交换是直接将两个字符进行对调,所以计算交换次数的时候不能只算一次。


__EOF__

本文作者神楽桜KaguraSakura
本文链接https://www.cnblogs.com/KaguraSakura/p/12703948.html
关于博主:hello~好久不见,喜欢的话点个赞吧
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   神楽桜KaguraSakura  阅读(498)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示