题意:
- 给定一个字符串,求这个字符串所有 连续子串 中,出现最多的字符次数减去出现最少的字符个数 的值 最大是多少。
思路:
- dp,字符串类型,尝试与 26 个字母联系
- ∣ s ∣ ≤ 1 0 6 ∣s∣≤10^6 ∣s∣≤106 ,要注意内存限制。
两种代码,细节注释。
C o d e : Code: Code:
#include<bits/stdc++.h>
#include<unordered_map>
#include<unordered_set>
#define mem(a,b) memset(a,b,sizeof a)
#define cinios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
#define forr(a,b,c) for(int a=b;a<=c;a++)
#define all(a) a.begin(),a.end()
#define sz(a) (int)a.size()
#define oper(a) operator<(const a& ee)const
#define endl '\n'
#define ul (u << 1)
#define ur (u << 1 | 1)
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const int N = 1e6 + 10, M = 2e5 + 10, mod = 1e8;
int INF = 0x3f3f3f3f; ll LNF = 0x3f3f3f3f3f3f3f3f;
int n, m, k;
int dp[2][26][26];
//只看后两位的话,dp[j][k] 代表 前 i 位形成的所有连续子串中,
//j 字符出现最多,k 字符出现最少的情况的最大差
//只看第一位,dp[0] 收集的是 j、k 字符有可能不存在的情况,
//dp[1] 收集的情况,j、k 字符都必须存在,这样最大差才合法
char s[N];
void solve() {
cin >> s + 1;
n = strlen(s + 1);
int ans = 0;
mem(dp[1], -0x3f);//初始字符都不存在,不合法
for (int i = 1; i <= n; i++) {
int u = s[i] - 'a';
//当前字符是什么,对应影响部分状态
for (int j = 0; j < 26; j++) {
if (u == j)continue;//相同没有意义
//当前出现 u ,u、j 状态最大差++
dp[0][u][j]++;
dp[1][u][j]++;
ans = max(ans, dp[1][u][j]);//随时维护最优解
}
for (int j = 0; j < 26; j++) {
if (u == j)continue;
//当前出现 u ,j、u 状态最大差--
dp[1][j][u]--;
dp[1][j][u] = max(dp[1][j][u], dp[0][j][u] - 1);
//一旦出现过一次 u,之后累计的 j、u 状态才有可能合法
//由 dp[0] 赋给 dp[1]
dp[0][j][u] = max(dp[0][j][u] - 1, 0);
// dp[0] 不需要维护负数
}
}
cout << ans;
}
int main() {
cinios;
int T = 1;
for (int t = 1; t <= T; t++)
solve();
return 0;
}
/*
*/
C o d e : Code: Code:
#include<bits/stdc++.h>
#include<unordered_map>
#include<unordered_set>
#define mem(a,b) memset(a,b,sizeof a)
#define cinios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
#define forr(a,b,c) for(int a=b;a<=c;a++)
#define all(a) a.begin(),a.end()
#define sz(a) (int)a.size()
#define oper(a) operator<(const a& ee)const
#define endl "\n"
#define ul (u << 1)
#define ur (u << 1 | 1)
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const int N = 1e6 + 10, M = 1e6 + 10, mod = 1e9 + 7;
int INF = 0x3f3f3f3f; ll LNF = 0x3f3f3f3f3f3f3f3f;
int n, m, k;
struct node
{
int w, f1, f2;
}dp[26][26];
char s[N];
void solve() {
cin >> s + 1;
n = strlen(s + 1);
int ans = 0;
for (int i = 1; i <= n; i++) {
int u = s[i] - 'a';
for (int j = 0; j < 26; j++) {
if (u == j)continue;
dp[u][j].w++;
if (dp[u][j].f1)ans = max(ans, dp[u][j].w);
//f1 标记 j 字符是否存在,不存在不能计入答案
dp[j][u].w = max(dp[j][u].w - 1, -1);
//最短也要是 -1,即只有一个 u 字符作为开头的情况,再短可舍去
dp[j][u].f1 = 1;//u 字符存在
if (dp[j][u].w == -1)dp[j][u].f2 = 1;//如果 u 字符开头就标记
else if (dp[j][u].f2) {
//在之后再次遇到 u 字符时,显然开头那个 u 可以舍去,也不影响 u 字符的存在性
dp[j][u].w++;//长度++
dp[j][u].f2 = 0;
}
}
}
cout << ans;
}
int main() {
cinios;
int T = 1;
for (int t = 1; t <= T; t++)
solve();
return 0;
}
/*
*/