Input: s ="abba"Output: 2Explanation:
Let's check the substring `"bb"`. You can see that no other `"b"`is outside
of this substring. Hence the answer is2.
Example 2:
1
2
3
4
5
6
Input: s ="abab"Output: -1Explanation:
Every substring we choose does not satisfy the described property(there issome character which is inside and outside of that substring). So the answer
would be -1.
Example 3:
1
2
3
4
5
6
Input: s ="abacd"Output: 4Explanation:
Let's check the substring `"abac"`. There is only one character outside of
this substring and that is`"d"`. There is no `"d"` inside the chosen
substring, so it satisfies the condition and the answer is4.
A substring is self-contained if all its characters are unique and do not appear outside the substring. We can use a sliding window to check all substrings, but to be efficient, we can precompute the first and last occurrence of each character and only consider substrings where all characters’ first and last occurrence are within the window.
classSolution {
public:int longestSelfContainedSubstring(string s) {
int n = s.size(), ans =-1;
vector<int> first(26, n), last(26, -1);
for (int i =0; i < n; ++i) {
int c = s[i] -'a';
first[c] = min(first[c], i);
last[c] = max(last[c], i);
}
for (int l =0; l < n; ++l) {
unordered_set<char> seen;
for (int r = l; r < n; ++r) {
char c = s[r];
if (seen.count(c)) break;
seen.insert(c);
int idx = c -'a';
if (first[idx] < l || last[idx] > r) continue;
if (r - l +1< n) ans = max(ans, r - l +1);
}
}
return ans;
}
};
classSolution {
publicintlongestSelfContainedSubstring(String s) {
int n = s.length(), ans =-1;
int[] first =newint[26], last =newint[26];
Arrays.fill(first, n);
Arrays.fill(last, -1);
for (int i = 0; i < n; i++) {
int idx = s.charAt(i) -'a';
first[idx]= Math.min(first[idx], i);
last[idx]= Math.max(last[idx], i);
}
for (int l = 0; l < n; l++) {
Set<Character> seen =new HashSet<>();
for (int r = l; r < n; r++) {
char c = s.charAt(r);
if (seen.contains(c)) break;
seen.add(c);
int idx = c -'a';
if (first[idx]< l || last[idx]> r) continue;
if (r - l + 1 < n) ans = Math.max(ans, r - l + 1);
}
}
return ans;
}
}
classSolution {
funlongestSelfContainedSubstring(s: String): Int {
val n = s.length
val first = IntArray(26) { n }
val last = IntArray(26) { -1 }
for (i in s.indices) {
val idx = s[i] - 'a' first[idx] = minOf(first[idx], i)
last[idx] = maxOf(last[idx], i)
}
var ans = -1for (l in0 until n) {
val seen = mutableSetOf<Char>()
for (r in l until n) {
val c = s[r]
if (c in seen) break seen.add(c)
val idx = c - 'a'if (first[idx] < l || last[idx] > r) continueif (r - l + 1 < n) ans = maxOf(ans, r - l + 1)
}
}
return ans
}
}
classSolution:
deflongestSelfContainedSubstring(self, s: str) -> int:
n = len(s)
first = {c: n for c in set(s)}
last = {c: -1for c in set(s)}
for i, c in enumerate(s):
first[c] = min(first[c], i)
last[c] = max(last[c], i)
ans =-1for l in range(n):
seen = set()
for r in range(l, n):
c = s[r]
if c in seen:
break seen.add(c)
if first[c] < l or last[c] > r:
continueif r - l +1< n:
ans = max(ans, r - l +1)
return ans
impl Solution {
pubfnlongest_self_contained_substring(s: String) -> i32 {
let n = s.len();
let s = s.as_bytes();
letmut first =vec![n; 26];
letmut last =vec![-1; 26];
for (i, &c) in s.iter().enumerate() {
let idx = (c -b'a') asusize;
if i < first[idx] { first[idx] = i; }
if i asi32> last[idx] { last[idx] = i asi32; }
}
letmut ans =-1;
for l in0..n {
letmut seen = std::collections::HashSet::new();
for r in l..n {
let c = s[r];
if!seen.insert(c) { break; }
let idx = (c -b'a') asusize;
if first[idx] < l || last[idx] > r asi32 { continue; }
if r - l +1< n && (r - l +1) asi32> ans { ans = (r - l +1) asi32; }
}
}
ans
}
}