本来是在做atcoder的题的,然后发现了这道几乎一样的题目。然而ac了这题,atcoder的papper sort却一直TLE。
思路:题目说的是给出一个字符串,问移动相邻的字符,最少需要多少次使其可以变成回文串。思路很简单,但是很多细节需要注意。先找与字符串最左边对应的,离最右边最近的字符,计算其移动到最优边所需移动的步数。然后删除二者,再在剩下的字符串中求解。由于删除如果用数组或者vector会很慢,做了一下优化改用双向链表。
开始不知道c++竟然有双项链表,用java打了一波,然而还是TLE,关键在atcoder的题上,用vector比用list还少tle一个答案,虽然其他数据List都要比vector版本来的快,不知道为什么,可能是写挫了,但是又不知道是什么数据,心情复杂。不过通过这个过程我又学了一下java的linkedlist和c++的list,也是挺好的。
c++:list的reverse_iterator运用参考此博文:https://www.cnblogs.com/SunboyL/p/reverse_iterator_erase.html
#include<iostream>
#include<cstring>
#include<string>
#include<vector>
#include<cstdio>
#include<list>
using namespace std;
const int maxn=1e6+50;
char s[maxn];
bool judge;
int length,cnte,cnto,cnt,temp,T,cnton,idx,t;
int main(){
//freopen("out.txt", "w", stdout);
while(scanf("%d",&t)!=EOF){
for(int i=0;i<t;i++){
scanf("%s",s);
list<int> ss;
list<int>::reverse_iterator rit;
judge=true;
length=strlen(s);
cnt=cnte=cnto=cnton=0;
for(int i=0;i<length;i++){
temp=s[i]-'a';
ss.push_back(temp);
v[temp].push_back(i);
}
for(int i=0;i<26;i++){
if(!v[i].size())
continue;
if(v[i].size()==length){///只有一个字母长度的时候
judge=false;
break;
}
if(v[i].size()%2)
cnto++;///奇数个数的字母
else
cnte++;///出现偶数个数的字母
}
if(length==1||!judge)///如果只有一个字母或全是相同的情况
printf("0\n");
else if((length%2&&cnte&&cnto<=1)||(!(length%2)&&!cnto)){///存在回文串
while(ss.size()){
judge=true;
idx=ss.size()-1;
for(rit=ss.rbegin();rit!=ss.rend()&&idx>0;rit++,idx--){///list的遍历
if(*rit==*ss.begin()){
cnt+=ss.size()-1-idx;
list<int>::iterator it=ss.erase((++rit).base());///rit不能直接用erase方法,要先转化成it,这里具体参考上述博客
rit=list<int>::reverse_iterator(it);
judge=false;
break;
}
}
ss.erase(ss.begin());
if(judge)
cnt+=ss.size()/2;///如果是单独的一个,则需要把它移动到中间
}
printf("%d\n",cnt);
}
else
printf("Impossible\n");
}
}
return 0;
}
java:
import java.util.LinkedList;
import java.util.Scanner;
class Main{
static int T;
public static void main(String[] args) {
Scanner scan=new Scanner(System.in);
while(scan.hasNextInt()){
T=scan.nextInt();
scan.nextLine();
for(int k=0;k<T;k++){
String s=new String();
boolean judge;
int length,cnt,cnte,cnto,temp,index;
int[] kinds=new int[26];
LinkedList<Integer> L=new LinkedList<Integer>();
s=scan.nextLine();
judge= true;
length=s.length();
cnt=cnte=cnto=0;
for(int i=0;i<length;i++){
temp=s.charAt(i)-'a';
L.add(temp);
kinds[temp]++;
}
for(int i=0;i<26;i++){
if(kinds[i]==0)
continue;
if(kinds[i]==length){
judge=false;
break;
}
if(kinds[i]%2==1)
cnto++;
else
cnte++;
}
//System.out.println(cnte+" "+cnto+" "+L.get(0)+" "+L.size());
if(length==1||!judge){
System.out.println("0");
}
else if((length%2==1&&cnte!=0&&cnto<=1)||(length%2==0&&cnto==0)){
while(L.size()!=0){
judge=true;
for(int j=L.size()-1;j>0;j--){
if(L.get(j)==L.getFirst()){
cnt+=L.size()-1-j;
L.remove(j);
judge=false;
break;
}
}
L.removeFirst();
if(judge){
cnt+=L.size()/2;
}
}
System.out.println(cnt);
}
else
System.out.println("Impossible");
}
}
}
}
对比一下觉得java的api实现起来人性化很多。