Foundations
Permutation in String
Fixed window frequency match: slide a window of len(s1) over s2 comparing character counts to detect any permutation of s1.
Problem
An intrusion-detection system flags suspicious character sequences: a message triggers an alert if any contiguous block of characters is a rearrangement of a known threat signature. Given the threat signature s1 and a message string s2, return true if any permutation of s1 appears as a contiguous substring of s2.
Example 1:
Input: s1 = "pq", s2 = "xonrqpkkk"
Output: True
Explanation: "rq" at index 3 is a permutation of s1.Example 2:
Input: s1 = "pq", s2 = "mpoqrs"
Output: FalseExample 3:
Input: s1 = "qpr", s2 = "rqpx"
Output: True
Explanation: "rqp" is a permutation of "qpr".Constraints:
1 <= s1.length, s2.length <= 10^4s1ands2consist of lowercase English letters.
Solution Breakdown
Approach: Fixed-size sliding window with frequency-map comparison.
Every permutation of s1 has exactly the same character multiset as s1, so a permutation of s1 exists in s2 iff some window of s2 of length k = len(s1) has identical character frequencies. Build s1_count = Counter(s1) once, then seed window_count = Counter(s2[:k]) for the first window and compare. To advance, slide the fixed window one position: add the entering character s2[end], decrement the leaving character s2[end - k], and delete its key when its count hits 0 so that Counter equality stays exact (a leftover 0 entry would make == fail). After each slide, window_count == s1_count answers whether that window is a permutation. Deleting zero-count keys is what lets a plain == comparison work - otherwise you would compare {'a': 0, 'b': 1} against {'b': 1} and get False.
Trace s1="pq", s2="xonrqpkkk": windows "xo", "on", "nr", then "rq" whose counts {r:1, q:1} equal s1_count - return True.
Edge cases: If k > len(s2) no window fits, so return False immediately. s1 == s2 checks the single full-length window. A length-1 pattern matches on the seeded window before the loop.
Complexity: O(n) time, O(1) space - the loop runs n times and each Counter comparison is bounded by the 26-letter alphabet; the two counters never exceed alphabet size.
Done reading? Mark it so it sticks in your dashboard.