Grandma Capa Knits a Scarf

传送门

题意:
一个字符串,要求删除其中的一种字符,使其变为回文串,要求删除的次数最少,求次数,如果不行输出-1


思路:
因为我不知道要删除哪个字符,所以我枚举所有的字符,问题就转换为我删这种字符是否可以是字符串变为回文串,删一个字符使字符串变为回文串的操作可以从两端不断的进行遍历移动,l, r, 判断两端是否相等,相等则l++, r--, 如果不相等,看看是否可以删除其中一个来使其进入下一个判断,最后如果都可以说明是可以删这个字符达到回文串的目的


证明:
假设一段回文串,问题就转换为这个回文串添加一种字符,那我从两端开始遍历,去删除这个字符一定能够让他重新变为回文,因为原先的字符只会和原先的字符进行匹配,最多也就加上一些添加的那种字符构成回文


总结:
删一个字符变回文,可以从两端开始遍历走,然后不知道要处理哪个字符时,可以想想数据范围,如果可以暴力枚举,直接暴力枚举

点击查看代码
#include <bits/stdc++.h>
#define endl '\n'
#define IOS ios::sync_with_stdio(false);
using namespace std;

typedef long long ll;

int T, n;
string s;

int main()
{
	IOS; cin.tie(0), cout.tie(0);
    cin >> T;
    while (T--)
    {
        cin >> n;
        cin >> s;
        int ans = 1E9;
        bool flag = true;
        for (int i = 0; i < 26; ++i)    //因为不知道要删除哪个,所以直接枚举,然后从两端进行删除,从两端进行删除就不用考虑从中间向两边时删除对原先已经构成的回文的影响
        {
            char c = i + 'a';
            int l = 0, r = s.size() - 1;
            int count = 0;
            flag = true;
            while (l <= r)
            {
                if (s[l] == s[r])
                    l++, r--;
                else
                {
                    if (s[l] == c)
                        l++, count++;
                    else if (s[r] == c)
                        r--, count++;
                    else
                    {
                        flag = false;
                        break;
                    }
                }    
            }

            if (flag)
            {
                ans = min(ans, count);
            }
        }

        if (ans != 1e9)
            cout << ans << endl;
        else
            cout << "-1" << endl;    
    }
	return 0;
}

posted @ 2022-09-12 10:57  YUGUOTIANQING  阅读(31)  评论(0)    收藏  举报