【问题描述】
“回文串”是一个正读和反读都一样的字符串,比如“level”或者“noon”等等就是回文串。给你一个字符串,问最少在字符串尾添加多少字符,可以使得字符串变为回文串。
【输入格式】
有多组测试数据。
每组测试数据第一行是一个正整数N,表示字符串长度,接下来一行是长度为N的字符串,字符串中只有小写字母。
N=0表示输入结束,并且不需要处理。
40%的数列元素个数N 1 ≤ N≤ 100;
30%的数列元素个数N 1 ≤ N≤ 1000;
20%的数列元素个数N 1 ≤ N≤ 10000;
10%的数列元素个数N 1 ≤ N≤ 100000;
【输出格式】
对于每组测试数据,输出一个非负整数:添加最少的字符数,可以使得字符串变为回文串。
【样例输入】
3 aba 4 aaac 0
【样例输出】
0 3
【思路】
我们首先从字符串的中间位置作为起点,向左右两边推进,只会有两种情况:
1.如果左右两边到了某个点不相等,说明这个情况没办法通过补右边让他对称,我们只能把起点向右移动一位,继续这个循环;
2.如果右边推进到了最后一位,说明此时【当前起点的左边有一部分】能和【起点的右边全部】是对称的,我们只需要补足此时左边和右边相差的数字就行了(而且我们的起点是从左往右移动的,此时找到的就是最小补足数目)
还有一点注意的是,起点右移一位并不是移动一位数,而是【数-缝隙-数】的移动,因为它可能补足之后是偶数个数字。
【AC代码】
#include<string>
#include<iostream>
#include<sstream>
using namespace std;
int main(){
int n;
while(cin>>n && n){
string s;
cin>>s;
int l_st,r_st;
if(n%2==0) { //偶数长度
l_st=n/2-1;
r_st=n/2;
int mini=n-1;
for(;r_st<=n-1;r_st++,l_st++){ //右起点最多到达最后一位
int j=l_st;
int i=r_st;
//缝隙为对称轴
int flag=1;
for(;i<=n-1;i++,j--){
if(s[j]!=s[i]){
flag=0;
break;
}
}
if(flag==1){
mini=l_st+1-(n-r_st);
break;
}
//r_st一个数为对称轴
flag=1;
i=r_st+1;
j=l_st;
for(;i<=n-1;i++,j--){
if(s[j]!=s[i]){
flag=0;
break;
}
}
if(flag==1){
mini=l_st+1-(n-r_st-1);
break;
}
}
cout<<mini<<'\n';
}else if(n%2!=0) { //奇数
//以中间的数作为对称轴 看看它是不是本身就对称
int cen=n/2;
int l=cen-1;
int r=cen+1;
int flag=1;
for(;r<=n-1;r++,l--){
if(s[r]!=s[l]){
flag=0;
break;
}
}
if(flag==1){
cout<<0<<'\n';
continue;
}
l_st=n/2;
r_st=n/2+1;
int mini=n-1;
//重复上面的【缝隙-数】循环
for(;r_st<=n-1;r_st++,l_st++){
int j=l_st;
int i=r_st;
//缝隙为对称轴
int flag=1;
for(;i<=n-1;i++,j--){
if(s[j]!=s[i]){
flag=0;
break;
}
}
if(flag==1){
mini=l_st+1-(n-r_st);
break;
}
//r_st一个数为对称轴
flag=1;
i=r_st+1;
j=l_st;
for(;i<=n-1;i++,j--){
if(s[j]!=s[i]){
flag=0;
break;
}
}
if(flag==1){
mini=l_st+1-(n-r_st-1);
break;
}
}
cout<<mini<<'\n';
}
}
}
【写在后面】
觉得对你有帮助的话记得一键三连哦~(误
相关题目放在了【HNU CJ】专栏
如果有啥问题可以评论留言或者私我哦~