You're given a string of lower-case Latin letters. Your task is to find the length of its longest substring that can be met in the string at least twice. These occurrences can overlap (see sample test 2).
The first input line contains the string. It's guaranteed, that the string is non-empty, consists of lower-case Latin letters, and its length doesn't exceed 100.
class Solution:
    """
    only append to answer if substring mei each letter length is greater.equal to k
    """    
    
    
    def longestSubstring_bruteforce_TLE(self, s: str, k: int) -> int:
        
        """
            T: O(n^2)
            
            . lets try brute force first
            a. find all substrings of s and check for given condition
                O(n^2) to make all substrings : 
                    i = 0 -> n , j = i+1 -> n 
                then checking for condition can be done using counter() so O(26)
        """
        
        if k == 1:
            return len(s)
        
        m = 0
        
        def all_k(c):
            for v in c.values():
                if v < k:
                    return False
            
            return True
        
        for i in range(len(s)):
            for j in range(i+1, len(s)):
                c = Counter(s[i:j + 1])
                if all_k(c):
                    m = max(m, j - i + 1)
        
        return m
    
    def longestSubstring_DIVIDE_AND_CONQUOR(self, s: str, k: int) -> int:
        """
            
            divide n conquor
            
            . from start to end, find pivot , divide and conquor .. so how to find pivot?
              pivot is places which will never be in answer which we can easily find. if count of something from start to end is less than k, it will never be answer
            
            q. how to know when to decrease window size?
            a. example
                "cbbacab", 2
                here its not even required to decrease window size
                    
                "bbaacbbaa", 2
                here at c , it makes sense to do it
                
                "aacbbrfrfgc", 2
                
                here if g , didnt now exist we donot need split
        """
        
        if k == 1:
            return len(s)
        
        def divide_n_conq(start, end):
            
            if start >= end:
                return 0
            
            c = Counter()
            
            for i in range(start, end + 1):
                c[s[i]] += 1
            
            for i in range(start, end + 1):
                curr = s[i]
                if c[curr] < k:
                    return max(divide_n_conq(start , i - 1), divide_n_conq(i + 1 , end))
            
            return end - start + 1
        
        return divide_n_conq(0, len(s) - 1)
        
        
    def longestSubstring(self, s: str, k: int) -> int:
        """ 
            . sliding window
            
            for sliding window, we need to know when to slide the window. here its not very obvious . 
            
            q. what good be good sliding strategies?
            a. we cannot slide on count of letter, 
            
            a. we have to try all unique letter substrings.. lemme explain
                . for s = "aacbbrfrfgc", k = 2
                unique letter = a, c, b, r, f, g, c
                total unique letters = 7
                
                now for i in range(7):
                    get_substring within s with maxximum i unique letter
                    
                    so for i = 1 (max unique letters in substring should be 1)
                        aa, c, bb, r, f, r, f, r, f, g, c : are all substrings with 1 unique letter
                    for i = 2 (max unique letters in substring should be 2)
                        aac, cbb, bbrfrf, rfrfg, ...
                    for i = 3 : (max unique letters in substring should be 3)
                        aacbb, cbbr ...
                    ...
                    
                    and return max ever found
                
                now this is not intuitive so lets see how can we come to this solution during interview when using sliding window
                now since we know its sliding window, we have to find , when to slide.. this now here need creative problem solving. 
                    . try sliding window based on letter count in window : this dont work bcz a letter can arrive in i+nth position and make the sequence valid so we need lookahead which doesnt look much possible
                    . 
                
        """
        
        c = Counter(s)
        unique_character = len(c)
        ans = 0
        
        for i in range(1, unique_character + 1):
            
            l = 0
            counter = defaultdict(int)
            for r in range(len(s)):
                curr = s[r]
                counter[curr] += 1
                
                while len(counter) > i:
                    counter[s[l]] -= 1
                    if counter[s[l]] == 0:
                        del counter[s[l]]
                    l += 1
                
                if all(j >= k for j in counter.values()):
                    ans = max(ans, r - l + 1)
        
        return ans
 					    		 	  				    			 	