public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        // 输入矩阵的行数和列数
        int n = sc.nextInt();
        int m = sc.nextInt();

        // 定义矩阵,存储所有数字
        int[][] matrix = new int[n][m];
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                matrix[i][j] = sc.nextInt();
            }
        }

        // 输入要求数组的长度 K
        int k = sc.nextInt();
        int[] reqArr = new int[k];
        for (int i = 0; i < k; i++) {
            reqArr[i] = sc.nextInt();
        }

        // 构造要求数字的频率字典(需要的数量)
        Map<Integer, Integer> need = new HashMap<>();
        for (int num : reqArr) {
            need.put(num, need.getOrDefault(num, 0) + 1);
        }

        // 预处理:统计每一列中各数字的出现频率,存入 colFreq 数组
        // colFreq[j] 表示第 j 列的数字及其出现次数
        List<Map<Integer, Integer>> colFreq = new ArrayList<>();
        for (int j = 0; j < m; j++) {
            Map<Integer, Integer> freq = new HashMap<>();
            for (int i = 0; i < n; i++) {
                int cur = matrix[i][j];
                freq.put(cur, freq.getOrDefault(cur, 0) + 1);
            }
            colFreq.add(freq);
        }

        // 使用滑动窗口在列上寻找最小宽度
        int left = 0;
        int ans = Integer.MAX_VALUE;
        Map<Integer, Integer> window = new HashMap<>();

        // 从左到右遍历所有列
        for (int right = 0; right < m; right++) {
            // 将当前右边界列的频率加到窗口中
            for (Map.Entry<Integer, Integer> entry : colFreq.get(right).entrySet()) {
                int key = entry.getKey();
                int value = entry.getValue();
                window.put(key, window.getOrDefault(key, 0) + value);
            }

            // 当窗口内满足所有需要的数字及数量时,尝试缩小窗口
            while (check(window, need)) {
                // 更新答案为当前窗口的宽度
                ans = Math.min(ans, right - left + 1);
                // 将左边界列的频率从窗口中移除
                for (Map.Entry<Integer, Integer> entry : colFreq.get(left).entrySet()) {
                    int key = entry.getKey();
                    int value = entry.getValue();
                    window.put(key, window.get(key) - value);
                }
                left++;  // 缩小窗口
            }
        }

        // 如果未找到满足要求的子矩阵,则输出 -1,否则输出最小宽度
        System.out.println(ans == Integer.MAX_VALUE ? -1 : ans);
    }

    // 检查窗口内的频率是否满足要求的频率
    private static boolean check(Map<Integer, Integer> window, Map<Integer, Integer> need) {
        for (Map.Entry<Integer, Integer> entry : need.entrySet()) {
            int key = entry.getKey();
            int count = entry.getValue();
            if (window.getOrDefault(key, 0) < count) {
                return false;
            }
        }
        return true;
    }
}

更多推荐