题目
给你一串字符串,你选择一种字符来删除使他变成回文字符串,选择了就只能删除字符串里的任意个数的这种字符。
求最少删除的次数。
题解思路
一开始没看清题目,以为任意都能删除。
后来发现只能选择一种,那样就很显然了。
直接找到第一个不同的字符对,删除他们两个其中一个。如果能得到回文串就取最小值。
之前相同的肯定不用删,因为加和不加他们对里面的回文串是没有影响的,删除他们反而得不到最优解。
考虑删除某个字符时,我们用双指针来跑,不同而且可以被删除就删,不能就得不到回文串。
可惜我模拟错了。真菜啊。
AC代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
#include <algorithm>
#include <map>
#include <string>
using namespace std;
const int INF = 0x3f3f3f3f;
char s[200100] ;
int main ()
{
ios::sync_with_stdio(false);cin.tie(0);
int T ;
cin >> T ;
while ( T -- )
{
int n ;
cin >> n ;
cin >> s ;
// cout << s << "\n" ;
int ans = n+1 , book = 0 ;
int p1 = 0 , p2 = n- 1 ;
while ( p1 < p2 )
{
if ( s[p1] != s[p2] )
{
book = 1 ;
char k1 = s[p1] ;
char k2 = s[p2] ;
int tmp = 0 ;
int t1 = p1 , t2 = p2 ;
while ( t1 < t2 )
{
if ( s[t1] == s[t2] )
{
t1++;
t2--;
}else if ( s[t1] == k1 )
{
t1++;
tmp++;
}else if ( s[t2] == k1 )
{
t2--;
tmp++;
}else
{
tmp = - 1 ;
break ;
}
}
if ( tmp != -1 )
{
ans = min( ans , tmp ) ;
}
tmp = 0 ;
t1 = p1 , t2 = p2 ;
while ( t1 < t2 )
{
if ( s[t1] == s[t2] )
{
t1++;
t2--;
}else if ( s[t1] == k2 )
{
t1++;
tmp++;
}else if ( s[t2] == k2 )
{
t2--;
tmp++;
}else
{
tmp = - 1 ;
break ;
}
}
if ( tmp != -1 )
{
ans = min( ans , tmp ) ;
}
break ;
}else
{
p1++ ;
p2-- ;
}
}
if (!book)
cout << "0\n" ;
else if ( ans != n+1 )
cout << ans << "\n" ;
else
cout << "-1\n" ;
}
return 0 ;
}