首页 > 试题广场 >

最短包含字符串的长度

[编程题]最短包含字符串的长度
  • 热度指数:2142 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
给定字符串str1和str2,求str1的字串中含有str2所有字符的最小字符串长度。

输入描述:
输入包括两行,第一行一个字符串,代表str1,第二行也是一个字符串,代表str2


输出描述:
输出str1的字串中含有str2所有字符的最小字符串长度,如果不存在请输出0。
示例1

输入

abcde
ac

输出

3

说明

“abc”中包含“ac”,且“abc”是所有满足条件中最小的。
示例2

输入

12345
344

输出

0
双指针滑动窗口求解(leftright双指针):
  1. 先统计str2的字符频数,以及总的字符负债debt=str2.length
  2. 遍历str1,利用right指针扩张右边界,遇到str2中没有的字符直接跳过,否则同步减少当前字符的计数和总的字符负债,但当计数小于0时,不再减小总的字符负债,因为出现字符的多余;
  3. debt=0时,表示在str1中找到了包含str2所有字符的子串,右移左指针left收缩左边界,直到排除所有多余字符(频数小于0的字符)后更新长度。
  4. 滑动窗口重复上面三个步骤,查找后面有没有更短的子串。
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.util.HashMap;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        char[] str1 = br.readLine().toCharArray();
        char[] str2 = br.readLine().toCharArray();
        HashMap<Character, Integer> termFreq = new HashMap<>();
        for(int i = 0; i < str2.length; i++) termFreq.put(str2[i], termFreq.getOrDefault(str2[i], 0) + 1);
        int left = 0, right = 0;
        int debt = str2.length;        // 刚开始欠str2长度的字符
        int minLen = str1.length + 1;
        while(right < str1.length){
            if(!termFreq.containsKey(str1[right])) {
                right ++;    // 跳过不相关的字符
                continue;
            }
            termFreq.put(str1[right], termFreq.getOrDefault(str1[right], 0) - 1);
            if(termFreq.get(str1[right]) >= 0) debt --;
            if(debt == 0){
                if(!termFreq.containsKey(str1[left])){
                    left ++;    // 跳过不相关的字符
                    continue;
                }
                // 负债小于0的词是多余的,先去掉
                while(termFreq.get(str1[left]) < 0){
                    termFreq.put(str1[left], termFreq.getOrDefault(str1[left], 0) + 1);
                    left ++;
                }
                // 负债为0且无多余词,更新长度
                minLen = Math.min(minLen, right - left + 1);
                termFreq.put(str1[left], termFreq.getOrDefault(str1[left], 0) + 1);
                debt ++;
                left ++;
            }
            right ++;
        }
        minLen = Math.min(minLen, right - left + 1);
        System.out.println(minLen == str1.length + 1? 0: minLen);
    }
}

编辑于 2021-11-27 17:55:17 回复(0)