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

给定一个字符串word和禁止字符串数组forbidden,目标是找到word中最长的不包含forbidden中任何字符串的子串。使用哈希表和双指针策略,通过移动右边界r并检查子串是否在禁止列表中,更新答案并移动左边界l来避免包含禁止字符串。
摘要由CSDN通过智能技术生成

题目: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<string>& forbidden) 
    {
        unordered_set<string> s(forbidden.begin(),forbidden.end());
        int n=word.size();
        int l=0,ans=0;
        for(int r=0;r<n;r++)
        {
            for(int i=r;i>=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;
    }
};

下一篇 最优屏障(栈)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值