力扣 567. 字符串的排列 滑动窗口

本文介绍了一种使用滑动窗口算法解决LeetCode上字符串排列问题的方法。通过维护一个固定大小的窗口,该算法可以高效地检查一个字符串是否包含另一个字符串的任意排列。文章详细解释了算法的实现过程,并提供了C++代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

https://leetcode-cn.com/problems/permutation-in-string/
在这里插入图片描述
思路:如果 s 2 s_2 s2包含 s 1 s_1 s1的排列,那么必定存在一个 s 2 s_2 s2的字串 s s s s s s中任意字符的出现次数一定等于 s 1 s_1 s1中对应字符的出现次数。转换到这一步就比较好搞了,当然暴力做还是会超时的,正解是滑动窗口。首先用 c n t cnt cnt数组记录 s 1 s_1 s1中每个字符的出现次数,然后令 l = r = 0 l=r=0 l=r=0(窗口的边界),我们不断移动右边界(入窗),当某个时候出现 c n t [ s 2 [ r ] − ′ a ′ ] < 0 cnt[s_2[r]-'a']<0 cnt[s2[r]a]<0时(不满足要求了),就需要移动左边界(出窗)。

class Solution {
public:
    bool checkInclusion(string s1, string s2) {
        vector<int> cnt(26,0);
        for(char ch:s1)
            ++cnt[ch-'a'];
        int l=0,r=0,siz1=s1.size(),siz2=s2.size();
        while(r<siz2){
            //r入窗
            --cnt[s2[r]-'a'];
            //不符合题意 l出窗
            while(cnt[s2[r]-'a']<0)
                ++cnt[s2[l++]-'a'];
            r++;
            if(r-l==siz1)
                return 1;
        }
        return 0;
    }
};
<think>好的,用户需要查找与信息学奥赛相关的字符串和数组的练习题及解法。首先,我得回忆一下信息学奥赛中常见的字符串和数组题目类型。通常这类题目涉及字符串处理、数组操作、算法应用等。比如,可能有字符串压缩、回文判断、子串查找、数组排序或搜索等问题。 用户提供的引用中有提到字符串压缩的例子,这对应力扣面试题01.06,所以这可能是一个相关题目。另外,引用中还提到KMP算法和STL数据结构,这些也是信息学奥赛中的常见考点。需要结合这些内容来生成相关的练习题。 接下来,我需要确定用户需要的不仅仅是题目名称,还有解法思路和示例代码。因此,每个练习题可能需要包括问题描述、解题思路、关键算法以及代码示例。同时,根据用户要求,要使用正确的中文和LaTeX格式,特别是行内数学公式用$...$,独立公式用$$...$$。 然后,需要确保引用的正确应用。用户提供的三个引用中,引用[1]是关于字符串压缩,引用[2]关于STL和next_permutation,引用[3]关于KMP算法。在回答时,如果提到这些相关算法或题目,需在末尾添加引用标识。 现在,列举一些常见的信息学奥赛字符串和数组题目: 1. 字符串压缩:类似力扣面试题01.06,要求将连续字符计数压缩,并处理边界情况。 2. 最长回文子串:使用中心扩展法或Manacher算法。 3. 实现KMP算法:处理字符串匹配,涉及next数组的构建。 4. 数组中的逆序对:利用归并排序进行统计。 5.排列问题:使用next_permutation函数生成排列。 6. 最长无重复子串:滑动窗口法的应用。 7. 字符串编辑距离:动态规划解法。 8. 旋转数组:三次翻转法或环状替换。 9. 字符串相乘:模拟竖式乘法的过程。 10. 数组中的第K大元素:快速选择算法。 对于每个问题,需要简要描述问题,分析解题思路,指出关键算法,并给出代码示例。例如,字符串压缩问题可以引用引用[1],KMP算法引用[3],全排列问题引用[2]。 需要确保代码示例正确,比如Python的实现,同时注意格式使用代码块包裹。此外,生成的相关问题需要围绕字符串和数组,可能涉及不同的算法如动态规划、双指针、分治等。 最后,检查是否符合用户的所有要求:结构清晰、正确引用、LaTeX格式、中文回答,以及生成相关问题。确保没有遗漏用户提到的任何要点,比如系统级指令中的格式要求。</think>### 信息学奥赛字符串/数组练习题及解法 #### 1. 字符串压缩(类似力扣面试题01.06) **问题**:将字符串压缩为连续字符+计数的形式,若压缩后长度不更短则返回原字符串。例如:$aabcccccaaa \rightarrow a2b1c5a3$[^1] **解法**:双指针遍历计数,注意字符边界。 **代码示例**: ```python def compress_string(s): if not s: return s res = [] cnt = 1 for i in range(1, len(s)): if s[i] == s[i-1]: cnt +=1 else: res.append(s[i-1] + str(cnt)) cnt = 1 res.append(s[-1] + str(cnt)) return min(s, "".join(res), key=len) ``` --- #### 2. 最长回文子串(动态规划/中心扩展) **问题**:求字符串中最长的回文子串。 **解法**:中心扩展法时间复杂度$O(n^2)$,空间$O(1)$。 **关键公式**:扩展半径$radius = \max(odd\_radius, even\_radius)$ **代码示例**: ```python def longest_palindrome(s): def expand(l, r): while l >=0 and r < len(s) and s[l]==s[r]: l -=1 r +=1 return r-l-1 start, max_len = 0,0 for i in range(len(s)): len1 = expand(i,i) len2 = expand(i,i+1) curr_len = max(len1, len2) if curr_len > max_len: max_len = curr_len start = i - (curr_len-1)//2 return s[start:start+max_len] ``` --- #### 3. KMP算法实现(字符串匹配) **问题**:在文本串中高效查找模式串的所有出现位置[^3]。 **关键步骤**:构建next数组,公式$next[i] = \max\{k \mid pattern[0:k] == pattern[i-k:i]\}$ **代码示例**: ```python def kmp(text, pattern): def build_next(p): next_arr = [0]*len(p) j = 0 for i in range(1, len(p)): while j >0 and p[i] != p[j]: j = next_arr[j-1] if p[i] == p[j]: j +=1 next_arr[i] = j return next_arr next_arr = build_next(pattern) res = [] j = 0 for i in range(len(text)): while j >0 and text[i] != pattern[j]: j = next_arr[j-1] if text[i] == pattern[j]: j +=1 if j == len(pattern): res.append(i - j +1) j = next_arr[j-1] return res ``` --- #### 4. 数组中的逆序对(归并排序应用) **问题**:计算数组中逆序对的总数。 **解法**:归并排序过程中统计跨子数组的逆序对,时间复杂度$O(n \log n)$。 **代码示例**: ```python def reverse_pairs(nums): def merge_sort(l, r): if l >= r: return 0 mid = (l + r) //2 count = merge_sort(l, mid) + merge_sort(mid+1, r) j = mid +1 for i in range(l, mid+1): while j <= r and nums[i] > 2 * nums[j]: j +=1 count += j - (mid+1) nums[l:r+1] = sorted(nums[l:r+1]) return count return merge_sort(0, len(nums)-1) ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值