classSolution: deflongestValidSubstring(self, word: str, forbidden: List[str]) -> int: fb = set(forbidden) ans = left = 0 for right inrange(len(word)): for i inrange(right, max(right - 10, left - 1), -1): if word[i: right + 1] in fb: left = i + 1# 当子串右端点 >= right 时,合法子串一定不能包含 word[i] break ans = max(ans, right - left + 1) return ans
[sol-Java]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
classSolution { publicintlongestValidSubstring(String word, List<String> forbidden) { varfb=newHashSet<String>(); fb.addAll(forbidden); intans=0, left = 0, n = word.length(); for (intright=0; right < n; right++) { for (inti= right; i >= left && i > right - 10; i--) { if (fb.contains(word.substring(i, right + 1))) { left = i + 1; // 当子串右端点 >= right 时,合法子串一定不能包含 word[i] break; } } ans = Math.max(ans, right - left + 1); } return ans; } }
[sol-C++]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
classSolution { public: intlongestValidSubstring(string word, vector<string> &forbidden){ unordered_set<string> fb{forbidden.begin(), forbidden.end()}; int ans = 0, left = 0, n = word.length(); for (int right = 0; right < n; right++) { for (int i = right; i >= left && i > right - 10; i--) { if (fb.count(word.substr(i, right - i + 1))) { left = i + 1; // 当子串右端点 >= right 时,合法子串一定不能包含 word[i] break; } } ans = max(ans, right - left + 1); } return ans; } };
funclongestValidSubstring(word string, forbidden []string) (ans int) { has := make(map[string]bool, len(forbidden)) for _, s := range forbidden { has[s] = true }
left := 0 for right := range word { for i := right; i >= left && i > right-10; i-- { if has[word[i:right+1]] { left = i + 1// 当子串右端点 >= right 时,合法子串一定不能包含 word[i] break } } ans = max(ans, right-left+1) } return }
funcmax(a, b int)int { if b > a { return b }; return a }
[sol-JavaScript]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
var longestValidSubstring = function (word, forbidden) { let fb = newSet(); for (const f of forbidden) fb.add(f); const n = word.length; let ans = 0, left = 0; for (let right = 0; right < n; right++) { for (let i = right; i >= left && i > right - 10; i--) { if (fb.has(word.substring(i, right + 1))) { left = i + 1; // 当子串右端点 >= right 时,合法子串一定不能包含 word[i] break; } } ans = Math.max(ans, right - left + 1); } return ans; };
复杂度分析
时间复杂度:\mathcal{O}(L+nM^2),其中 L 为所有 forbidden}[i] 的长度之和,n 为 word 的长度,M=10 表示 forbidden}[i] 的最长长度。请注意,在哈希表中查询一个长为 M 的字符串的时间是 \mathcal{O}(M),每次移动右指针会执行至多 M 次这样的查询。