Array 
      
    
      
      
      
        String 
      
    
      
      
      
        Trie 
      
    
   
  
    
      
       
     
  
  
    
      
    
    
      
       
     
  
    
Description 
You are given an array of strings words and an integer k.
For each index i in the range [0, words.length - 1], find the length  of the longest common prefix   among any k strings (selected at distinct indices ) from the remaining array after removing the ith  element.
Return an array answer, where answer[i] is the answer for ith  element. If removing the ith  element leaves the array with fewer than k strings, answer[i] is 0.
 
Example 1: 
Input:  words = ["jump","run","run","jump","run"], k = 2 
Output:  [3,4,4,3,4] 
Explanation: 
    Removing index 0 ("jump"):
    
        words becomes: ["run", "run", "jump", "run"]. "run" occurs 3 times. Choosing any two gives the longest common prefix "run" (length 3). 
     
     
    Removing index 1 ("run"):
    
        words becomes: ["jump", "run", "jump", "run"]. "jump" occurs twice. Choosing these two gives the longest common prefix "jump" (length 4). 
     
     
    Removing index 2 ("run"):
    
        words becomes: ["jump", "run", "jump", "run"]. "jump" occurs twice. Choosing these two gives the longest common prefix "jump" (length 4). 
     
     
    Removing index 3 ("jump"):
    
        words becomes: ["jump", "run", "run", "run"]. "run" occurs 3 times. Choosing any two gives the longest common prefix "run" (length 3). 
     
     
    Removing index 4 ("run"):
    
        words becomes: ["jump", "run", "run", "jump"]. "jump" occurs twice. Choosing these two gives the longest common prefix "jump" (length 4). 
     
     
 
 
Example 2: 
Input:  words = ["dog","racer","car"], k = 2 
Output:  [0,0,0] 
Explanation: 
    Removing any index results in an answer of 0. 
 
 
 
Constraints: 
    1 <= k <= words.length <= 105  
    1 <= words[i].length <= 104  
    words[i] consists of lowercase English letters. 
    The sum of words[i].length is smaller than or equal 105 . 
 
Solutions 
Solution 1 
Python3 Java C++ Go 
  1 
  2 
  3 
  4 
  5 
  6 
  7 
  8 
  9 
 10 
 11 
 12 
 13 
 14 
 15 
 16 
 17 
 18 
 19 
 20 
 21 
 22 
 23 
 24 
 25 
 26 
 27 
 28 
 29 
 30 
 31 
 32 
 33 
 34 
 35 
 36 
 37 
 38 
 39 
 40 
 41 
 42 
 43 
 44 
 45 
 46 
 47 
 48 
 49 
 50 
 51 
 52 
 53 
 54 
 55 
 56 
 57 
 58 
 59 
 60 
 61 
 62 
 63 
 64 
 65 
 66 
 67 
 68 
 69 
 70 
 71 
 72 
 73 
 74 
 75 
 76 
 77 
 78 
 79 
 80 
 81 
 82 
 83 
 84 
 85 
 86 
 87 
 88 
 89 
 90 
 91 
 92 
 93 
 94 
 95 
 96 
 97 
 98 
 99 
100 
101 
102 
103 
104 
105 
106 
107 
108 
109 
110 
111 
112 
113 
114 
115 
116 
117 
118 
119 
120 
121 
122 
123 
124 
125 
126 
127 
128 
129 
130 class  Solution   { 
     static   class  TrieNode   { 
         int   count   =   0 ; 
         int   depth   =   0 ; 
         int []   children   =   new   int [ 26 ] ; 
         TrieNode ()   { 
             for   ( int   i   =   0 ;   i   <   26 ;   ++ i )   children [ i ]   =   - 1 ; 
         } 
     } 
     static   class  SegmentTree   { 
         int   n ; 
         int []   tree ; 
         int []   globalCount ; 
         SegmentTree ( int   n ,   int []   globalCount )   { 
             this . n   =   n ; 
             this . globalCount   =   globalCount ; 
             this . tree   =   new   int [ 4   *   ( n   +   1 ) ] ; 
             for   ( int   i   =   0 ;   i   <   tree . length ;   i ++ )   tree [ i ]   =   - 1 ; 
             build ( 1 ,   1 ,   n ); 
         } 
         void   build ( int   idx ,   int   l ,   int   r )   { 
             if   ( l   ==   r )   { 
                 tree [ idx ]   =   globalCount [ l ]   >   0   ?   l   :   - 1 ; 
                 return ; 
             } 
             int   mid   =   ( l   +   r )   /   2 ; 
             build ( idx   *   2 ,   l ,   mid ); 
             build ( idx   *   2   +   1 ,   mid   +   1 ,   r ); 
             tree [ idx ]   =   Math . max ( tree [ idx   *   2 ] ,   tree [ idx   *   2   +   1 ] ); 
         } 
         void   update ( int   idx ,   int   l ,   int   r ,   int   pos ,   int   newVal )   { 
             if   ( l   ==   r )   { 
                 tree [ idx ]   =   newVal   >   0   ?   l   :   - 1 ; 
                 return ; 
             } 
             int   mid   =   ( l   +   r )   /   2 ; 
             if   ( pos   <=   mid )   { 
                 update ( idx   *   2 ,   l ,   mid ,   pos ,   newVal ); 
             }   else   { 
                 update ( idx   *   2   +   1 ,   mid   +   1 ,   r ,   pos ,   newVal ); 
             } 
             tree [ idx ]   =   Math . max ( tree [ idx   *   2 ] ,   tree [ idx   *   2   +   1 ] ); 
         } 
         int   query ()   { 
             return   tree [ 1 ] ; 
         } 
     } 
     public   int []   longestCommonPrefix ( String []   words ,   int   k )   { 
         int   n   =   words . length ; 
         int []   ans   =   new   int [ n ] ; 
         if   ( n   -   1   <   k )   return   ans ; 
         ArrayList < TrieNode >   trie   =   new   ArrayList <> (); 
         trie . add ( new   TrieNode ()); 
         for   ( String   word   :   words )   { 
             int   cur   =   0 ; 
             for   ( char   c   :   word . toCharArray ())   { 
                 int   idx   =   c   -   'a' ; 
                 if   ( trie . get ( cur ). children [ idx ]   ==   - 1 )   { 
                     trie . get ( cur ). children [ idx ]   =   trie . size (); 
                     TrieNode   node   =   new   TrieNode (); 
                     node . depth   =   trie . get ( cur ). depth   +   1 ; 
                     trie . add ( node ); 
                 } 
                 cur   =   trie . get ( cur ). children [ idx ] ; 
                 trie . get ( cur ). count ++ ; 
             } 
         } 
         int   maxDepth   =   0 ; 
         for   ( int   i   =   1 ;   i   <   trie . size ();   ++ i )   { 
             if   ( trie . get ( i ). count   >=   k )   { 
                 maxDepth   =   Math . max ( maxDepth ,   trie . get ( i ). depth ); 
             } 
         } 
         int []   globalCount   =   new   int [ maxDepth   +   1 ] ; 
         for   ( int   i   =   1 ;   i   <   trie . size ();   ++ i )   { 
             TrieNode   node   =   trie . get ( i ); 
             if   ( node . count   >=   k   &&   node . depth   <=   maxDepth )   { 
                 globalCount [ node . depth ]++ ; 
             } 
         } 
         List < List < Integer >>   fragileList   =   new   ArrayList <> (); 
         for   ( int   i   =   0 ;   i   <   n ;   ++ i )   { 
             fragileList . add ( new   ArrayList <> ()); 
         } 
         for   ( int   i   =   0 ;   i   <   n ;   ++ i )   { 
             int   cur   =   0 ; 
             for   ( char   c   :   words [ i ] . toCharArray ())   { 
                 int   idx   =   c   -   'a' ; 
                 cur   =   trie . get ( cur ). children [ idx ] ; 
                 if   ( trie . get ( cur ). count   ==   k )   { 
                     fragileList . get ( i ). add ( trie . get ( cur ). depth ); 
                 } 
             } 
         } 
         int   segSize   =   maxDepth ; 
         if   ( segSize   >=   1 )   { 
             SegmentTree   segTree   =   new   SegmentTree ( segSize ,   globalCount ); 
             for   ( int   i   =   0 ;   i   <   n ;   ++ i )   { 
                 if   ( n   -   1   <   k )   { 
                     ans [ i ]   =   0 ; 
                 }   else   { 
                     for   ( int   d   :   fragileList . get ( i ))   { 
                         segTree . update ( 1 ,   1 ,   segSize ,   d ,   globalCount [ d ]   -   1 ); 
                     } 
                     int   res   =   segTree . query (); 
                     ans [ i ]   =   res   ==   - 1   ?   0   :   res ; 
                     for   ( int   d   :   fragileList . get ( i ))   { 
                         segTree . update ( 1 ,   1 ,   segSize ,   d ,   globalCount [ d ] ); 
                     } 
                 } 
             } 
         } 
         return   ans ; 
     } 
} 
 
 
  1 
  2 
  3 
  4 
  5 
  6 
  7 
  8 
  9 
 10 
 11 
 12 
 13 
 14 
 15 
 16 
 17 
 18 
 19 
 20 
 21 
 22 
 23 
 24 
 25 
 26 
 27 
 28 
 29 
 30 
 31 
 32 
 33 
 34 
 35 
 36 
 37 
 38 
 39 
 40 
 41 
 42 
 43 
 44 
 45 
 46 
 47 
 48 
 49 
 50 
 51 
 52 
 53 
 54 
 55 
 56 
 57 
 58 
 59 
 60 
 61 
 62 
 63 
 64 
 65 
 66 
 67 
 68 
 69 
 70 
 71 
 72 
 73 
 74 
 75 
 76 
 77 
 78 
 79 
 80 
 81 
 82 
 83 
 84 
 85 
 86 
 87 
 88 
 89 
 90 
 91 
 92 
 93 
 94 
 95 
 96 
 97 
 98 
 99 
100 
101 
102 
103 
104 
105 
106 
107 class   Solution   { 
public : 
     struct   TrieNode   { 
         int   count   =   0 ; 
         int   depth   =   0 ; 
         int   children [ 26 ]   =   { 0 }; 
     }; 
     class   SegmentTree   { 
     public : 
         int   n ; 
         vector < int >   tree ; 
         vector < int >&   globalCount ; 
         SegmentTree ( int   n ,   vector < int >&   globalCount ) 
             :   n ( n ) 
             ,   globalCount ( globalCount )   { 
             tree . assign ( 4   *   ( n   +   1 ),   -1 ); 
             build ( 1 ,   1 ,   n ); 
         } 
         void   build ( int   idx ,   int   l ,   int   r )   { 
             if   ( l   ==   r )   { 
                 tree [ idx ]   =   globalCount [ l ]   >   0   ?   l   :   -1 ; 
                 return ; 
             } 
             int   mid   =   ( l   +   r )   /   2 ; 
             build ( idx   *   2 ,   l ,   mid ); 
             build ( idx   *   2   +   1 ,   mid   +   1 ,   r ); 
             tree [ idx ]   =   max ( tree [ idx   *   2 ],   tree [ idx   *   2   +   1 ]); 
         } 
         void   update ( int   idx ,   int   l ,   int   r ,   int   pos ,   int   newVal )   { 
             if   ( l   ==   r )   { 
                 tree [ idx ]   =   newVal   >   0   ?   l   :   -1 ; 
                 return ; 
             } 
             int   mid   =   ( l   +   r )   /   2 ; 
             if   ( pos   <=   mid ) 
                 update ( idx   *   2 ,   l ,   mid ,   pos ,   newVal ); 
             else 
                 update ( idx   *   2   +   1 ,   mid   +   1 ,   r ,   pos ,   newVal ); 
             tree [ idx ]   =   max ( tree [ idx   *   2 ],   tree [ idx   *   2   +   1 ]); 
         } 
         int   query ()   { 
             return   tree [ 1 ]; 
         } 
     }; 
     vector < int >   longestCommonPrefix ( vector < string >&   words ,   int   k )   { 
         int   n   =   words . size (); 
         vector < int >   ans ( n ,   0 ); 
         if   ( n   -   1   <   k )   return   ans ; 
         vector < TrieNode >   trie ( 1 ); 
         for   ( const   string &   word   :   words )   { 
             int   cur   =   0 ; 
             for   ( char   c   :   word )   { 
                 int   idx   =   c   -   'a' ; 
                 if   ( trie [ cur ]. children [ idx ]   ==   0 )   { 
                     trie [ cur ]. children [ idx ]   =   trie . size (); 
                     trie . push_back ({ 0 ,   trie [ cur ]. depth   +   1 }); 
                 } 
                 cur   =   trie [ cur ]. children [ idx ]; 
                 trie [ cur ]. count ++ ; 
             } 
         } 
         int   maxDepth   =   0 ; 
         for   ( int   i   =   1 ;   i   <   trie . size ();   ++ i )   { 
             if   ( trie [ i ]. count   >=   k )   { 
                 maxDepth   =   max ( maxDepth ,   trie [ i ]. depth ); 
             } 
         } 
         vector < int >   globalCount ( maxDepth   +   1 ,   0 ); 
         for   ( int   i   =   1 ;   i   <   trie . size ();   ++ i )   { 
             if   ( trie [ i ]. count   >=   k   &&   trie [ i ]. depth   <=   maxDepth )   { 
                 globalCount [ trie [ i ]. depth ] ++ ; 
             } 
         } 
         vector < vector < int >>   fragileList ( n ); 
         for   ( int   i   =   0 ;   i   <   n ;   ++ i )   { 
             int   cur   =   0 ; 
             for   ( char   c   :   words [ i ])   { 
                 int   idx   =   c   -   'a' ; 
                 cur   =   trie [ cur ]. children [ idx ]; 
                 if   ( trie [ cur ]. count   ==   k )   { 
                     fragileList [ i ]. push_back ( trie [ cur ]. depth ); 
                 } 
             } 
         } 
         int   segSize   =   maxDepth ; 
         if   ( segSize   >=   1 )   { 
             SegmentTree   segTree ( segSize ,   globalCount ); 
             for   ( int   i   =   0 ;   i   <   n ;   ++ i )   { 
                 if   ( n   -   1   <   k )   { 
                     ans [ i ]   =   0 ; 
                 }   else   { 
                     for   ( int   d   :   fragileList [ i ])   { 
                         segTree . update ( 1 ,   1 ,   segSize ,   d ,   globalCount [ d ]   -   1 ); 
                     } 
                     int   res   =   segTree . query (); 
                     ans [ i ]   =   res   ==   -1   ?   0   :   res ; 
                     for   ( int   d   :   fragileList [ i ])   { 
                         segTree . update ( 1 ,   1 ,   segSize ,   d ,   globalCount [ d ]); 
                     } 
                 } 
             } 
         } 
         return   ans ; 
     } 
}; 
 
 
 
 
  
  
  
    
    
    
    
      
  
    
      
  
     
   
  GitHub