1156. 单字符重复子串的最大长度
- 问题描述
- 问题分析
- 解决方案
问题描述
1156. 单字符重复子串的最大长度
如果字符串中的所有字符都相同,那么这个字符串是单字符重复的字符串。
给你一个字符串 text,你只能交换其中两个字符一次或者什么都不做,然后得到一些单字符重复的子串。返回其中最长的子串的长度。
- 示例 1:
输入:text = “ababa”
输出:3 - 示例 2:
输入:text = “aaabaaa”
输出:6 - 示例 3:
输入:text = “aaabbaaa”
输出:4 - 示例 4:
输入:text = “aaaaa”
输出:5 - 示例 5:
输入:text = “abcdef”
输出:1
问题分析
对于该问题,我第一反应就是这个怎么做?
动态规划?发现不知道状态转移方程怎么写
贪心算法?不知道怎么选下一节点
那就考虑老老实实的采用“笨办法”怎么实现的,先遍历字符串统计每个连续字符的长度,后面怎么交换来获得最长的字符串呢?
看着统计后的信息,问题可以转化为片段的拼接问题:对每个字符的相邻片段进行拼接,找到最长的的片段,其中相邻片段是指两个片段相隔一个字符,且只能进行一次拼接。
解决方案
在代码实现中,统计信息是(起始位置,下一个不同字符的位置)
class Solution {
public:
int maxRepOpt1(string text) {
unordered_map<char, vector<pair<int, int>>> len;
int start = 0;
while(start < text.length()){
int end = start + 1;
while(end < text.length()){
if(text[start] != text[end]){
break;
}
end++;
}
//注意:这里的统计信息是(起始位置,下一个不同字符的位置)
len[text[start]].push_back(make_pair(start, end));
start = end;
}
int maxLen = 1;
for(auto [ch, lens]: len){
//单片段的长度,当有多个片段,此时可以用其他片段给该片段补充一个字符,所以需要 加上 (lens.size() > 1)
int cnt = lens[0].second - lens[0].first + (lens.size() > 1);
//按顺序遍历片段,只对相邻片段进行拼接
for(int idx = 1; idx < lens.size(); ++idx){
int l = lens[idx].second - lens[idx].first + (lens.size() > 1);
//检查是否相邻:如果跟上一个片段相差一个字符,则考虑拼接
if(lens[idx].first - 1 == lens[idx - 1].second){
l += lens[idx - 1].second - lens[idx - 1].first;
//当该字符的片段列表为2时,这两个片段之间的拼接就必须使用自身字符拼接,因为上面已经提前+1了,所以这里要减去1
if(lens.size() == 2){
l -= 1;
}
}
if(l > cnt){
cnt = l;
}
}
if(maxLen < cnt){
maxLen = cnt;
}
}
return maxLen;
}
};