代码源:557、删删

305 阅读2分钟

本文已参与[新人创作礼]活动,一起开启掘金创作之路 logo.png

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情

题目描述

这是3月16日代码源div2的每日一题。

知识点:双指针

删删 - 题目 - Daimayuan Online Judge

给定一个字符串,你可以删除多个(可以是 0) 相同 的字符,这样操作之后,你能否得到一个回文串?如果能,求最小化删除的个数。

输入格式

多组数据。

每一组数据包含两行,分别为字符串的长度 N,以及一个仅由小写字母组成的字符串 SS。

输出格式

对于每一组数据,输出一行。

如果不可能得到一个回文串,输出 −1。反之则输出最小操作次数。

样例输入

4
8
bilibili
3
qwq
9
daimayuan
7
xcpcxpc

样例输出

1
0
-1
2

解释:

在第一个例子中,删除开头的 b 得到 ilibili

第二个例子中,qwq 本身已回文,不需要操作。

第三个例子中,可以看到 daimayuan 不能靠仅删除一种字符得到一个回文串。

数据规模

  • 1≤N≤10^5, 但保证 ∑N≤2×10^5

问题解析

太菜了,自己只能想到个暴力解法。

枚举26个字符,假设这个字符就是这个字符串要删除的字符,然后双指针跑字符串,当两边不一样时就判断两边有没有那边是我们当前枚举的字符,如果有就跳过他,操作数++然后继续双指针跑字符串,如果两边都没有我们当前枚举的字符,说明这个字符不能把字符串变成回文,我们去枚举下一个字符,如果有字符可以把字符串变成回文,那就把操作数记录下来,并维护最小值。最后如果所有字符都不能把字符串变成回文那就输出-1,反之输出最小的操作数。

#include<iostream>
using namespace std;
#include<vector>
#include<string>
#include<string.h>

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    int t;
    cin >> t;
    
    while (t--)
    {
        char c = '#';
        int n,res=1e9;
        bool flag = true;
        string str;
        cin >> n >> str;
        for (char i = 'a'; i <= 'z'; i++)
        {
            bool flag = true;
            int l = 0, r = n - 1,ans=0;
            while (l < r)
            {
                if (str[l] == str[r])l++, r--;
                else
                {
                    if (str[l] == i)l++, ans++;
                    else if (str[r] == i)r--, ans++;
                    else
                    {
                        flag = false;
                        break;
                    }
                }
            }
            if (flag)res = min(res, ans);
        }
        if (res==1e9)cout << -1 << '\n';
        else cout << res << '\n';
    }
    return 0;
}