力扣1156——单字符重复子串的最大长度(分割字符串+分类讨论)

题目(中等)

如果字符串中的所有字符都相同,那么这个字符串是单字符重复的字符串。

给你一个字符串 text,你只能交换其中两个字符一次或者什么都不做,然后得到一些单字符重复的子串。返回其中最长的子串的长度。

示例 1:

输入:text = “ababa”
输出:3
示例 2:

输入:text = “aaabaaa”
输出:6
示例 3:

输入:text = “aaabbaaa”
输出:4
示例 4:

输入:text = “aaaaa”
输出:5
示例 5:

输入:text = “abcdef”
输出:1

提示:

1 <= text.length <= 20000
text 仅由小写英文字母组成。

解题思路

分割字符串+分类讨论
首先将整个字符串按连续相同字母一段进行分割存words里,存储每段的起点和长度(由起点可以得到对应字母);
并统计每种字母出现次数,连续只算一次;
分类讨论:
1、不进行操作,那就是words里的最长长度;
2、长度可+1,例如aaaaaabbbbaa,字母为a的段出现过两次,可通过交换使长度+1;
3、两者可合并,可由其他位置填补,例如aaabaacccca,前三段中,第一段第三段相同,且第二段长度为1,并且a在别处也出现,可达长度为 第一段+第三段+1
4、两者可合并,但没其他可补,例如aaabaaccc,只能中间的b和第一段或第三段中一个进行更换,可达长度为 第一段+第三段

记录其中最大值即是答案。

代码

class Solution {
public:
    int maxRepOpt1(string text) {
        int n = text.size();
        if(n == 1) return 1;
        vector<pair<int, int> > words;  //存每段起点和长度
        unordered_map<char, int> hash;  //字母及出现次数
        int ans = 0, cnt = 1, begin = 0;
        for(int i = 1; i < n; i++) {
            if(text[i] == text[begin]) cnt++;
            else {
                words.push_back({begin, cnt});
                hash[text[begin]]++;
                begin = i;
                ans = max(ans, cnt);
                cnt = 1;
            }
        }
        words.push_back({begin, cnt});
        hash[text[begin]]++;
        ans = max(ans, cnt);
        int wordn = words.size();
        if(wordn < 3) return ans; 
        for(auto [b, l] : words) {      //每段能否多1
            if(hash[text[b]] > 1) ans = max(ans, l + 1);
        }
        for(int i = 2; i < wordn; i++) {    //两段可拼接,两边一样且中间长度为1
            if(text[words[i-2].first] == text[words[i].first] && words[i-1].second == 1) {
                if(hash[text[words[i].first]] > 2) ans = max(ans, words[i-2].second + words[i].second + 1);
                else ans = max(ans, words[i-2].second + words[i].second);
            }
        }
        return ans;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值