该算法由Jay Kadane 于1984年最先提出,其中使用了动态规划的思想,时间复杂度为$O(n)$。其中的证明应该是显而易见的。
其算法的主要是计算以结尾为$i$的字符串中的最大的字串。当不能够存在空的字串的时候存在以下的递推方程:
$$\begin{equation} f(i)=
\begin{cases} f(i-1)+a[i]& \text{ $ f[i-1]>0 $ } \\
a[i]& \text{ $ f[i-1]<=0 $ }
\end{cases}
\end{equation} $$
当能够使用空字串的时候,其中的递推方程如下:
$$\begin{equation} f(i)=
\begin{cases} f(i-1)+a[i]& \text{ $ f[i-1]+a[i]>0 $ } \\
0& \text{ $ f[i-1]+a[i]<=0 $ }
\end{cases}
\end{equation} $$
相关题目(待补充):
LeetCode 2272:
题目要求是找出有最大两种字母出现的差值的子字符串,由于其中有的字母的数量有限(仅26个小写字母)实际上可以枚举需要比较的所有两种字符,然后把其中一种字符赋值为1,另外一种字符赋值为-1,然后使用上面的Kadane算法进行处理。不过需要注意的是其中的要求是在子字符串中两种字符都需要至少出现一次才能统计差值。我在这其中的处理是添加了一个变量用来判断是否出现第二种字符,如果在以$i$结尾的字符串中没有出现被赋值为-1的字符类型b,则把最终结果-1。因为当目标的字符串中没有出现b,则此时则肯定需要找到一个最近的b,并且把目标的字符串延长直到包括第一个b,因此结果需要-1。
class Solution {
public:
int getMaxVariance(string s, char a, char b) {
int n = s.length();
int count=0;
int maxVar = 0;
int var = 0;
bool hasb = false;
for (int i = 0; i < n; i++) {
if (s[i] == a) {
var++;
if (var > maxVar && hasb) {
maxVar = var;
}
if (hasb) {
if (var>maxVar) maxVar = var;
} else {
if (var-1>maxVar) maxVar = var-1;
}
} else if (s[i] == b) {
if (var > 0) {
var--;
hasb = true;
}
else {
var = 0;
hasb = false;
}
}
}
return maxVar;
}
int largestVariance(string s) {
int maxVar = 0;
int c[26];
memset(c,0,sizeof(c));
int l = s.length();
for (int i = 0; i < l; i++) {
c[s[i]-'a'] ++;
}
for (char i = 'a'; i <= 'z'; i++) {
for (char j = 'a'; j <= 'z'; j++) {
if (i == j) continue;
if (c[i-'a'] == 0 || c[j-'a'] == 0) continue;
int k = getMaxVariance(s,i,j);
if (k>maxVar) maxVar = k;
}
}
return maxVar;
}
};