Codeforces#750div2
C-Grandma Capa Knits a Scarf
题目描述
Grandma Capa决定去织一条围巾,她让Grandpa Sher给她制作一个图形,这个图形就是一个由小写的英文字母组成得字符串。Grandpa Sher写下了一个长度为 n 的字符串s。
Grandma Capa想要织出一条漂亮的围巾,在她看来,一条漂亮的围巾只能由一个回文字符串织成。她想要改变Grandpa Sher提供的图案,为了避免使他厌烦,她将会选择一个小写的英文字母,并且在字符串s中删除一些这个字母。注意,她只能选择一个字母去删除。
她也想最小化删除字母的数量,请你帮她找到最小的她需要删除字母的数量,使字符串s变成一个回文字符串。
输入描述
第一行包含一个整数t(1 <= t <= 100)代表由 t 组测试样例。接下来的 2*t 行来描述样例,每组测试样例包含两行。
第一行一个整数 n (1 <= n <= 1e5) 代表字符串的长度。
第二行包含一个长度为 n 仅由小写英文字母构成的字符串。
确保所有样例的 n 之和不大于 2e5
输出描述
对于每组样例输出最少需要删除的字母数量,如果不能使其变成回文串,则输出-1
Input
5
8
abcaacab
6
xyzxyz
4
abba
8
rprarlap
10
khyyhhyhky
Output
2
-1
0
3
2
解题思路
对于一个给定的字符串,比如abcaacab,我们假设选择通过删除 ‘a’ 来使字符串变成回文串。根据回文串的性质,我们比较abcaacab的最左边和最右边,发现不相等,但是有一边是‘a’,所以我们可以先把‘a’删除了,得到bcaacab,再比较发现相同了,然后继续比较第二个和倒数第二个,发现不相同,但一边仍然有‘a’,因此可以删除‘a’继续比较,即bcaacb,后面的比较都相同了。因此,我们得到了如果选则删除‘a’的话,需要删除2个。同理,看删除‘b’...‘z’需要多少个,取最小值。比较的时候有4种情况,
1.左边跟右边相同
2.左边跟右边不同,但左边的可被删去(即等于所选择删除的字符)
3.左边跟右边不同,但右边可被删去
4.左边跟右边不同,两边都不能被删去(遇到这种,说明这种方法不成立,需要换一个字母删)
AC代码
#include <bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
string s;
int t,n,cnt;
void solve() {
int ans = INF;
cin >> n >> s;
for(char i = 'a'; i <= 'z'; i++){
int l = 0,r = n - 1;
cnt = 0;
while(l < r){
if(s[l] == s[r]) l++,r--;
else if(s[l] == i) l++,cnt++;
else if(s[r] == i) r--,cnt++;
else break;
}
if(l >= r && ans > cnt) ans = cnt;
}
if(ans == INF) ans = -1;
cout << ans << endl;
}
int main(){
cin >> t;
while(t--){
solve();
}
return 0;
}