有任何问题可以在下面留言
题意:
回文字符串 s1 可以随意切割任意次,问最少切割几次,可以获得一个新的回文字符串 s2 ( s1 ! = s2 ) ,切割出来的字符串,可以任意拼接,但是不能反转。
思路:
先想明白一点,无论任何情况,只要能生成合法的s2 ,最多切割2次;
解释: s1 本身是回文的,如果能合法拼成s2, 两边对调下,也就是最多切割两次。所以现在问题就是看 s1 能不能 1次切割就行。最后那个样例起到了警示作用。
先分情况:s: 的长度
奇数:
- 全部的字母相同,肯定是 Impossible
- 两种字母,两边全部是相同的字母,最中间的字母是另一种,也是 Impossible
偶数:
- 全部的字母相同,Impossible
特殊情况 已经考虑完了,刚刚解释了 最多切割两次,那现在就要看能不能1次切割就合法。s1 的序列长度 n 是<=5000的 尝试下从头到尾枚举切割位置,然后拼接,得到 s2, 既要不等于s1 还要是 回文串。 算下复杂度 n*n/2, tnnd,是不是有种这题 怎么会是div2-D 的难度呢。
代码:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int main(){
string s;
cin>>s;
int dis[30]={0};
int mark=0;
for(int i=0;i<s.length();i++){
dis[s[i]-'a']++;
if(dis[s[i]-'a']==1){
mark++;
}
}
bool jkl=false;
if(mark==1){
cout<<"Impossible"<<endl;
}else if(mark==2&&dis[s[1]-'a']==s.length()-1&&dis[s[s.length()/2]-'a']==1){
cout<<"Impossible"<<endl;
}else{
for(int i=1;i<s.length();i++){
string now1=s.substr(0,i);
string now2=s.substr(i,s.length()-i);
string jug=now2+now1;
if(jug!=s){
bool op=false;
for(int i=0;i<jug.length()/2;i++){
if(jug[i]!=jug[jug.length()-i-1]){
op=true;
break;
}
}
if(!op){
jkl=true;
}
}
}
if(jkl){
cout<<"1"<<endl;
}else{
cout<<"2"<<endl;
}
}
}