题意:
给你一个长度为n的01字符串,你必须对这个字符串进行一次(只能进行一次)操作:选择一个l,r (1<=l<=r<=n),使范围内的字符串1变成0,0变成1,问你变换后的字符串是否是回文串?
思路
因为目的是要把字符串变成回文串,那么可以从两端往中间遍历,如果不相同就在右边区域标记一下用来表示这个地方需要取反操作。然后再遍历一遍看需要取反操作的区域是不是连续的,如果是就说明可以构成回文串,不是连续的就说明不能构成。
代码
#include<cstdio>
#include <iostream>
#include <algorithm>
#include <string.h>
#include <string>
#include <math.h>
#include<vector>
#include<queue>
#include<map>
#define sc_int(x) scanf("%d", &x)
#define sc_ll(x) scanf("%lld", &x)
#define pr_ll(x) printf("%lld", x)
#define pr_ll_n(x) printf("%lld\n", x)
#define pr_int_n(x) printf("%d\n", x)
#define ll long long
using namespace std;
const int N=1000000+100;
int n ,m,h;
char s[N];
bool k[N];
void slove( )
{
int t;
sc_int(n);
cin>>s+1;
bool st=0;
for(int i =1,j=n;i<j;i++,j--)
{
if(s[i]!=s[j])
k[j]=1;
}
for(int i =1;i<=n;i++)
{
if(k[i]==1)
{
if(!st)st=1;
else {
cout<<"no\n";
for(int i =1;i<=n;i++)k[i]=0;
return ;
}
int j=i;
while(k[j+1]==1&&j+1<=n)j++;
i=j;
}
}
for(int i =1;i<=n;i++)k[i]=0;
cout<<"Yes\n";
return ;
}
int main()
{
int t;
sc_int(t);
while(t--)
slove();
return 0;
}