最长子串

📃题目#

给定一个字符串,找出包含最多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的时候,那种成就感让人还想再来一题

作者:Rauze

出处:https://www.cnblogs.com/rauze/p/18122893

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

posted @   Rauze  阅读(13)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示
more_horiz
keyboard_arrow_up dark_mode palette
选择主题
menu