最大長反復の最長繰り返し部分文字列を単一の文字列の場合1156スワップ
説明
文字列内のすべての文字が同じである場合、その文字列は単一の文字列が繰り返されています。
あなたの文字列を付けtext
、1つのまたは2つの文字が何もしないでいる入れ替えることができ、その後、いくつかの単一文字の繰り返し部分文字列を取得します。最長の部分文字列の長さを返します。
例1:
入力:テキスト=「アベバ」
出力:3
説明:我々は最後の「A」と、または最初の「A」と最後の「b」を置き換えるために最初の「b」を置き換えることができます。次いで、文字の最長のサブストリングを繰り返すと、その長さは、「AAA」である3例2:
入力:テキスト=「aaabaaa」
出力:6
説明:最後の「A」(または最初の「A」)を使用して「b」を置き換える、私たちは、最長繰り返し文字部分文字列「AAA」を取得し、その長さは6であります例3:
入力:テキスト= "aaabbaaa"
出力:4例4:
入力:テキスト=「AAAAA」
出力:5
説明:無交換は、最も長い部分文字列が文字を繰り返されていない「AAA」、5の長さを例5:
入力:テキスト= "ABCDEF"
出力:1ヒント:
1 <= text.length <= 20000
テキストのみ小文字の英文字。
考え
ウィンドウスライディング考え
左右マージン、および拡張することができた「ウィンドウ」、維持するために
、この問題は、開始位置の「ウィンドウ」を右に移動し、
1)元の文字位置、+ 1に等しく、
2)に等しくありません、その後、何もありません右側に見る為替の同じ文字がと何もありませんフォールトトレラントスペース(旧1は、使用0の後、)
- 注:特別の事情
「AABA」この交換は、右の文字を持っていますが、(等しいが許容できない)、その後フォールトトレラント文字、結果は文字の周波数を超える計算します
コードの実装
class Solution {
public int maxRepOpt1(String text) {
if (null == text | text.length() <= 0) return 0;
int len = text.length();
char[] chs = text.toCharArray();
//cnt 字符串中所出现字符的频数
int[] cnt = new int[30];
// type 字符串中字符种类
int type = 0;
for (char c : chs) {
int ind=c-'a';
if (cnt[ind]==0) type++;
cnt[ind]++;
}
// 字符串中字符没有重复
if (type == len) return 1;
// 字符串中字符全部单字符重复
if (type == 1) return len;
// size 重复子串最大长度/滑动窗口最大长度
int size = 0;
for (int i = 0; i < len;) {
char begin = chs[i];
// now 当前重复子串最大长度
// time 容错余裕 可以结合字符频数提前判断
// cnt[begin-'a']==1 --> time=0 没有可以交换字符 容错余裕为0
// next 下一个窗口开始位置(因为i++ 会导致有些计算冗余 可以直接从容错位置开始)
int now = 0, time = 1, next=i+1;
// 滑动窗口向右扩展
for (int j = i; j < len; j++) {
// 相等
if (chs[j]==begin) now++;
// 不相等 但有容错和可交换字符
else if ((time-- > 0) && (cnt[begin-'a']-now >= 1)) {now++; next=j;}
else break;
}
// 特殊情况 计算长度必定不大于字符频数
now = now > cnt[begin-'a'] ? cnt[begin-'a'] : now;
// 比较原最大长度与当前长度
size = now > size ? now : size;
i = next;
}
return size;
}
}