1. 题目来源
链接:3789. 隐藏字符串
2. 题目解析
猜结论就行了。最优解一定是长度为 1 的,或者长度为 2 的子串。
因为如果长度大于 3 并且还是等差数列的话,那么长度为 1、2 的子串一定也包含在其中,所以,所以最优解一定在长度为 1、2 的子串中包含的有。
计算:
- 长度为 1:直接遍历每个字母取出现次数最高的即可。
- 长度为 2:前缀和
f[i][j]
统计字母ij
出现的次数,因为仅有 26 * 26 种情况。 - 即,假设当前枚举的是以字符
x
,结尾的字符串,那么以ax, bx, cx,...,xx, yx, zx
这 26 种情况均以x
作为结尾,它们分别出现的次数就是a,b,c,...,x,y,z
这些字符所出现的次数。 - 故,仅需统计一个字符出现次数的
s
数组,和f[26][26]
的所有长度为 2 的出现次数统计即可。 - 注意在枚举当前位置
t
时,不要先将其计数,应该是计算完f[][]
的所有状态之后再对其计数,s[t] ++
,因为以t
结尾,那么必然t
不能成为自己的开头,所以不能计数。
时间复杂度: O ( 26 n ) O(26n) O(26n)
空间复杂度: O ( 26 ∗ 26 ) O(26*26) O(26∗26)
枚举所有长度为 2 的字符串出现次数即可。
#include <bits/stdc++.h>
using namespace std;
using LL = long long;
LL s[26], f[26][26];
int main() {
string str;
cin >> str;
LL res = 0;
for (char i : str) {
int t = i - 'a';
for (int j = 0; j < 26; j ++ ) {
f[j][t] += s[j]; // 以t结尾的长度为2的字符串出现次数
res = max(res, f[j][t]); // 长度为2,更新答案
}
s[t] ++ ; // 在后面累加s[t]++,枚举以自己结尾的字符串时,自己不应该加入计数中
res = max(res, s[t]); // 长度为1,更新答案
}
cout << res << endl;
return 0;
}