---
# System prepended metadata

title: "\n"

---

2781. Length of the Longest Valid Substring


```javs=
1. g[i], f[i] 的關係還是沒有很懂 
2. 下面的 case 會 fails
"cbaaaabc"
["aaa","cb"]

f[i] : 在 s[i] 開頭，最短的 forbidden string 長度
g[i] : 以 i 開頭的最長合法 substring 長度


forbidden : ["de", "le", "e"]


index: 0 1 2 3 4 5 6 7
s[i] : l e e t c o d e
f[i] : 2 1 1 x x x 2 1
g[i] : 1 0 0 4 3 2 1 0


g[i+1] = \min_{j>=i+1} { j + f[j] - 1 } - (i+1)
g[i] =   \min_{j>=i  } { j + f[j] - 1 } - i


Trie


class Solution {
    public int longestValidSubstring(String word, List<String> forbidden) {
        Set<String> forbiddenSet = new HashSet<>();
        forbiddenSet.addAll(forbidden);
        
        int n = word.length();
        int [] f = new int [n];
        Arrays.fill(f, Integer.MAX_VALUE/2);
        
        for(int i = 0; i < n; i ++){
           for(int j = i; j <= n; j++){
               String str = word.substring(i, j);
               if(forbiddenSet.contains(str)){
                  f[i] = Math.min(f[i], str.length());  
               }
           } 
        }
        
        int g[] = new int [n];
         Arrays.fill(g, Integer.MAX_VALUE/2);
       
        int max = 0;
        
        for(int i = 0; i < n; i ++){
           for(int j = i; j < n; j ++){
              if(j + f[j]  - i >= 0){
                 g[i] = Math.min(g[i], j + f[j] - 1 - i);
              } 
          
           } 
           if(g[i] != Integer.MAX_VALUE/2) 
               max = Math.max(max, g[i]); 
        }
        /*
        f[i] : 在 s[i] 開頭，最短的 forbidden string 長度
        g[i] : 以 i 開頭的最長合法 substring 長度

        */

        // System.out.println(Arrays.toString(f));
        // System.out.println(Arrays.toString(g));
        return max;
    }
}

```

``` java=
class Solution {
    public int longestValidSubstring(String word, List<String> forbidden) {
        Set<String> visited = new HashSet<>(forbidden);
        
        int n = word.length();
        int size = 0;
        
        StringBuilder sb = new StringBuilder();
        
        for(int i = 0; i < n; i++){
            sb.append(word.charAt(i)+"");
            int len = sb.length();
            for(int j = len - 1; j >= Math.max(0, len - 10); j --){
                String str = sb.substring(j);
               
                if(visited.contains(str)){
                    //  為什麼這裡會這樣寫
                    //  System.out.println("before:" +  sb.toString());
                    // System.out.println(str);
                    sb.delete(0, j + 1);
                    // System.out.println("after:" + sb.toString()); 
                    break;
                }
            }
            // System.out.println("result:" + sb.toString()); 
            
            // sb 是以 i 結尾的最長合法 substring
            
            // 1 2 [3 4 5 7 8] 9 10 11 12
            // 1 2 [3 4 5 7 8 9] 10 11 12
            
            size = Math.max(size, sb.length());
            
        }
        return size;
    }
}


```


### 2781 AC
```java=
class Solution {
    public int longestValidSubstring(String word, List<String> forbidden) {
        Set<String> forbiddenSet = new HashSet<>();
        forbiddenSet.addAll(forbidden);
        
        int n = word.length();
        int [] f = new int [n];
        Arrays.fill(f, Integer.MAX_VALUE/2);
        
        for(int i = 0; i < n; i ++){
           for(int j = i; j <= n && j <= i + 10; j++){
               String str = word.substring(i, j);
               if(forbiddenSet.contains(str)){
                  f[i] = Math.min(f[i], str.length());  
               }
           } 
        }
        
        int g[] = new int [n];
         Arrays.fill(g, Integer.MAX_VALUE/2);
       
        int max = 0;
        
        for (int i = n - 1; i >= 0; i--) {
            g[i] = n - i;
            if (i + 1 < n) g[i] = Math.min(g[i], g[i+1] + 1);
            g[i] = Math.min(g[i], f[i] - 1); // i 開頭的 forbidden string
            max = Math.max(max, g[i]); 
        }
        /*
        f[i] : 在 s[i] 開頭，最短的 forbidden string 長度
        g[i] : 以 i 開頭的最長合法 substring 長度

        */

        // System.out.println(Arrays.toString(f));
        // System.out.println(Arrays.toString(g));
        return max;
    }
}

/*
     i :  0 1 2 3 4 5 6 7
   s[i]:  c b a a a a b c
   f[i]:  2 x 3 3 x x x x
   g[i]:  1 3 2 2 x x x x


   f[i] : 以 i 開頭最短的 forbidden
   g[i] = \min (n-i) ,\min_{j>=i} { j + f[j] - 1 - i }


   g[i-1] = \min (n-(i-1)), \min_{j>=(i-1)} { j + f[j] - 1 - (i-1) }
          = \min (n-(i)), \min_{j>=i} { j + f[j] - 1 - i} + 1, f[i-1]-1
          = \min g[i] + 1, f[i-1]-1
*/

```