Given a string s
and an integer k
, find the number of pairs of equal substrings of length k
such that the absolute difference between their starting indices is minimized (i.e., for each unique substring, count the number of pairs of occurrences with the smallest possible index difference).
Specifically, for every substring of length k
that appears more than once in s
, consider all pairs of starting indices (i, j)
such that s[i:i+k] == s[j:j+k]
and i < j
. For each such substring, only count the pair(s) with the minimum absolute difference in indices. Sum this count over all unique substrings of length k
.
The naive approach is to check every pair of substrings of length k
and count those that are equal, then find which pairs have the smallest index difference for each substring. However, this is inefficient because the number of substrings grows rapidly as the input size increases.
To optimize, we can:
k
using a hash map.Let's break down the steps:
k
:
s
and, for each position i
, extract s[i:i+k]
.i
in a hash map where the key is the substring.This method is efficient because it avoids redundant comparisons and leverages efficient data structures for grouping and searching.
Suppose s = "ababcab"
and k = 2
.
k
.The optimized approach is efficient for large inputs, as it avoids unnecessary comparisons.
This problem challenges us to efficiently count pairs of equal substrings with the smallest possible index difference. By grouping substring occurrences and focusing on minimal gaps between indices, we avoid brute-force inefficiency. The key insight is that, for each unique substring, consecutive occurrences determine the minimal difference, leading to an elegant and performant solution.
from collections import defaultdict
def count_min_diff_pairs(s: str, k: int) -> int:
substr_indices = defaultdict(list)
n = len(s)
for i in range(n - k + 1):
substr = s[i:i+k]
substr_indices[substr].append(i)
total = 0
for indices in substr_indices.values():
if len(indices) < 2:
continue
indices.sort()
min_diff = float('inf')
for i in range(1, len(indices)):
min_diff = min(min_diff, indices[i] - indices[i-1])
count = 0
for i in range(1, len(indices)):
if indices[i] - indices[i-1] == min_diff:
count += 1
total += count
return total
#include <unordered_map>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
int countMinDiffPairs(string s, int k) {
unordered_map<string, vector<int>> substrIndices;
int n = s.size();
for (int i = 0; i <= n - k; ++i) {
substrIndices[s.substr(i, k)].push_back(i);
}
int total = 0;
for (auto &pair : substrIndices) {
vector<int>& indices = pair.second;
if (indices.size() < 2) continue;
sort(indices.begin(), indices.end());
int minDiff = INT_MAX;
for (int i = 1; i < indices.size(); ++i) {
minDiff = min(minDiff, indices[i] - indices[i-1]);
}
int count = 0;
for (int i = 1; i < indices.size(); ++i) {
if (indices[i] - indices[i-1] == minDiff) count++;
}
total += count;
}
return total;
}
import java.util.*;
public class Solution {
public int countMinDiffPairs(String s, int k) {
Map<String, List<Integer>> substrIndices = new HashMap<>();
int n = s.length();
for (int i = 0; i <= n - k; ++i) {
String sub = s.substring(i, i + k);
substrIndices.computeIfAbsent(sub, x -> new ArrayList<>()).add(i);
}
int total = 0;
for (List<Integer> indices : substrIndices.values()) {
if (indices.size() < 2) continue;
Collections.sort(indices);
int minDiff = Integer.MAX_VALUE;
for (int i = 1; i < indices.size(); ++i) {
minDiff = Math.min(minDiff, indices.get(i) - indices.get(i-1));
}
int count = 0;
for (int i = 1; i < indices.size(); ++i) {
if (indices.get(i) - indices.get(i-1) == minDiff) count++;
}
total += count;
}
return total;
}
}
function countMinDiffPairs(s, k) {
const substrIndices = {};
const n = s.length;
for (let i = 0; i <= n - k; ++i) {
const sub = s.substring(i, i + k);
if (!(sub in substrIndices)) substrIndices[sub] = [];
substrIndices[sub].push(i);
}
let total = 0;
for (const indices of Object.values(substrIndices)) {
if (indices.length < 2) continue;
indices.sort((a, b) => a - b);
let minDiff = Infinity;
for (let i = 1; i < indices.length; ++i) {
minDiff = Math.min(minDiff, indices[i] - indices[i-1]);
}
let count = 0;
for (let i = 1; i < indices.length; ++i) {
if (indices[i] - indices[i-1] === minDiff) count++;
}
total += count;
}
return total;
}