ZhangZhihui's Blog  

You are given a string s and an array of strings words. All the strings of words are of the same length.

A concatenated string is a string that exactly contains all the strings of any permutation of words concatenated.

  • For example, if words = ["ab","cd","ef"], then "abcdef""abefcd""cdabef""cdefab""efabcd", and "efcdab" are all concatenated strings. "acdbef" is not a concatenated string because it is not the concatenation of any permutation of words.

Return an array of the starting indices of all the concatenated substrings in s. You can return the answer in any order.

 

Example 1:

Input: s = "barfoothefoobarman", words = ["foo","bar"]

Output: [0,9]

Explanation:

The substring starting at 0 is "barfoo". It is the concatenation of ["bar","foo"] which is a permutation of words.
The substring starting at 9 is "foobar". It is the concatenation of ["foo","bar"] which is a permutation of words.

Example 2:

Input: s = "wordgoodgoodgoodbestword", words = ["word","good","best","word"]

Output: []

Explanation:

There is no concatenated substring.

Example 3:

Input: s = "barfoofoobarthefoobarman", words = ["bar","foo","the"]

Output: [6,9,12]

Explanation:

The substring starting at 6 is "foobarthe". It is the concatenation of ["foo","bar","the"].
The substring starting at 9 is "barthefoo". It is the concatenation of ["bar","the","foo"].
The substring starting at 12 is "thefoobar". It is the concatenation of ["the","foo","bar"].

 

Constraints:

    • 1 <= s.length <= 104
    • 1 <= words.length <= 5000
    • 1 <= words[i].length <= 30
    • s and words[i] consist of lowercase English letters.

 

ChatGPT's Solution:

from collections import Counter


class Solution(object):
    def findSubstring(self, s, words):
        """
        :type s: str
        :type words: List[str]
        :rtype: List[int]
        """
        
        if not s or not words:
            return []
        
        word_len = len(words[0])
        word_count = len(words)
        total_len = word_len * word_count
        word_map = Counter(words)
        result = []

        for i in range(word_len):
            left, right = i, i
            curr_map = Counter()
            while right + word_len <= len(s):
                word = s[right:right + word_len]
                right += word_len
                if word in word_map:
                    curr_map[word] += 1
                    while curr_map[word] > word_map[word]:
                        curr_map[s[left:left + word_len]] -= 1
                        left += word_len
                    if right - left == total_len:
                        result.append(left)
                else:
                    curr_map.clear()
                    left = right
        
        return result

 

Explanation:

  1. Precompute Data:

    • Store word frequencies in word_map using Counter.
    • Calculate the total length of concatenated words.
  2. Sliding Window Technique:

    • Iterate through s with different starting indices to cover all possible word alignments.
    • Expand the window by moving right and checking if the current word exists in words.
    • If the frequency of any word exceeds the allowed count, move left forward.
    • If the window matches the total length of all words, store the starting index.

This solution efficiently finds all valid substrings in O(N * word_len), making it suitable for large inputs.

 

 

posted on 2025-03-15 16:03  ZhangZhihuiAAA  阅读(41)  评论(0)    收藏  举报