【力扣】第354场周赛 (最长合法子字符串的长度)

题目:6924. 最长合法子字符串的长度

给你一个字符串 word 和一个字符串数组 forbidden 。

如果一个字符串不包含 forbidden 中的任何字符串,我们称这个字符串是 合法 的。

请你返回字符串 word 的一个 最长合法子字符串 的长度。

子字符串 指的是一个字符串中一段连续的字符,它可以为空。

示例 1:

输入:word = "cbaaaabc", forbidden = ["aaa","cb"]
输出:4
解释:总共有 9 个合法子字符串:"c" ,"b" ,"a" ,"ba" ,"aa" ,"bc" ,"baa" ,"aab" 和 "aabc" 。最长合法子字符串的长度为 4 。
其他子字符串都要么包含 "aaa" ,要么包含 "cb" 。

示例 2:

输入:word = "leetcode", forbidden = ["de","le","e"]
输出:4
解释:总共有 11 个合法子字符串:"l" ,"t" ,"c" ,"o" ,"d" ,"tc" ,"co" ,"od" ,"tco" ,"cod" 和 "tcod" 。最长合法子字符串的长度为 4 。
所有其他子字符串都至少包含 "de" ,"le" 和 "e" 之一。

提示:

1 <= word.length <= 1e5
word 只包含小写英文字母。
1 <= forbidden.length <= 1e5
1 <= forbidden[i].length <= 10
forbidden[i] 只包含小写英文字母。

思路:哈希表+双指针

初始化子串左端点 l=0,枚举子串右端点 r。

对于示例 2,只要 r ≥1,那么合法子串是不能包含 le 的,所以左端点 l 必须向右移,不可能再回到 0(否则就包含  le 了)。因为左端点只会向右移动,不会向左移动,这样的单调性保证了算法的效率。

当r 右移到一个新的字母时,枚举以该字母为右端点的 forbidden[i] 的最短长度。如果发现子串 word[i] 到 word[right] 在 forbidden 中(用哈希表实现),那么更新 l =i+1 并结束枚举,从而避免合法子串包含 forbidden 中的字符串。枚举结束后,更新答案为合法子串长度 r −l +1 的最大值。

AC代码:

class Solution {
public:
    int longestValidSubstring(string word, vector& forbidden) 
    {
        unordered_set s(forbidden.begin(),forbidden.end());
        int n=word.size();
        int l=0,ans=0;
        for(int r=0;r=l&&i>r-10;i--)
            {
                if(s.count(word.substr(i,r-i+1)))
                {
                    l=i+1;
                    break;
                }
            }
            ans=max(ans,r-l+1);
        }
        return ans;
    }
};

下一篇 最优屏障(栈)

你可能感兴趣的:(leetcode,算法,职场和发展,c++)