最长子串
📃题目#
给定一个字符串,找出包含最多2个不同字符的最长子串长度
示例 1:
输入:axyxxxxyyyxdddadayx
输出:10
解释:其中符合条件的最长子串是 xyxxxxyyyx,子串中只包含x和y两个不同字符
🤔思路#
子串问题第一反应想到了动态规划,开始动规五部曲分析
1、确定dp数组以及下标含义
dp数组应该是几维呢?
设置一维的话,dp[i]中应该存放的是以下标i结尾符合要求的字符串长度,但是在判断字符串是否符合要求时,我们还需要额外的信息——该字符串中不同字符的个数
因此dp数组设置成为二维,即dp[i][j],i与一维的定义相同,而j表示以下标i结尾,有j+1个不同字符。
2、确定递推公式
在递推过程中存在两种情况:
当前字符与前一个字符相等,即s[i]==s[i-1]
dp[i][0] = dp[i-1][0] + 1;
// 因为dp[i-1][1]>dp[i-1][0],所以不用考虑dp[i-1][0]+1的情况
dp[i][1] = dp[i-1][1] + 1;
当前字符与前一个字符不相等,即s[i]≠s[i-1]
//只能有一个不同字符,那么只能是s[i]这一个了
dp[i][0] = 1;
dp[i][1] = dp[i-1][0] + 1;
dp[i][1]乍一看感觉没问题,但是运行的时候,它忽略了一种场景,即以i-1结尾有两个不同字符的字符串,其中一个字符与s[i]相同,那么这种情况应该是dp[i][1] = dp[i-1][1] + 1
那么如何去判断另外一个”不知道位置“的字符是否与s[i]相同呢
其实这个位置与dp[i-1][1]息息相关,可以通过i-dp[i-1][1]-1获得另一个字符的下标位置,因为[i-dp[i-1][1],i-1]这个区间内的都是相同字符
所以第二种情况的递推公式,代码如下:
//只能有一个不同字符,那么只能是s[i]这一个了
dp[i][0] = 1;
if (s[i] != s[i - dp[i - 1][0] - 1]) dp[i][1] = dp[i - 1][0] + 1;
else dp[i][1] = dp[i - 1][1] + 1;
3、dp数组如何初始化
数组需要初始化的是dp[0][0]和dp[0][1],两个分别表示下标i字符结尾有1个不同字符和有2个不同字符的字符串长度,从实际结果上看长度都是1
4、确定遍历顺序
从递推公式上可以看出,dp[i]需要dp[i-1]计算,所以应该从上至下计算
5、举例推导公式
使用字符串前半部分axyxxxxy为例
dp[i][j] | 0 | 1 |
---|---|---|
0 | 1 | 1 |
1 | 1 | 2 |
2 | 1 | 2 |
3 | 1 | 3 |
4 | 2 | 4 |
5 | 3 | 5 |
6 | 4 | 6 |
7 | 1 | 7 |
最终遍历dp数组寻找最大值得到结果
代码如下:
#include <bits/stdc++.h>
using namespace std;
int main() {
string s;
cin >> s;
vector<vector<int>> dp(s.size(), vector<int>(2, 0));
dp[0][0] = 1;
dp[0][1] = 1;
for (int i = 1; i < s.size(); i++) {
if (s[i] == s[i - 1]) {
dp[i][0] = dp[i - 1][0] + 1;
dp[i][1] = dp[i - 1][1] + 1;
} else {
dp[i][0] = 1;
if (s[i] != s[i - dp[i - 1][0] - 1]) dp[i][1] = dp[i - 1][0] + 1;
else dp[i][1] = dp[i - 1][1] + 1;
}
cout << dp[i][1] << endl;
}
int result = dp[0][1];
for (int i = 1; i < s.size(); i++) {
result = max(result, dp[i][1]);
}
cout << result;
return 0;
}
🔚总结#
本题属于动态规划类型的题目,只是在递推公式的细节上需要琢磨,通过dp[i-1][0]处理不同字符是否重合是题目的关键,否则会卡测试案例
虽然是基础算法的稍微改进,但是自己构想写出来并提交AC的时候,那种成就感让人还想再来一题
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· .NET10 - 预览版1新功能体验(一)