# *- coding:utf-8 -*
'''
这道题感觉难度不小,想了好长时间,没有找到最优解法,看到大神们用一种
滑动窗口方法,确实经典。
滑动窗口思路:
一个窗口长度是恒定的(与一个单词长度相等),滑动一次窗口的长度,查看目前
窗口组成的word是否在words中,并要保证word只出现一次,记录状态;如果word满足条件,
就继续向右移动窗口得到新的word重复上述过程,当所有的word在words中连续找到时,记录
位置;如果word不在words中,清除记录的状态,窗口
继续移动。当遍历到s结尾处时,则从s[i]出重新开始上述过程(i<窗口长度)
具体实现:
字符串s的长度为s_len,每个单词的长度为w_len,(滑动窗口每次移动w_len)那么遍历顺序
为 0,w_len,2*w_len,....n*w_len (s_len-w_len<=n*w_len<=s_len),第二次遍历的顺序每个
点向右一定一个字符即:1,w_len+1,2*w_len+1,....,n*w_len+1(s_len-w_len<=n*w_len+1<=s_len),
一次类推,进行上述w_len次,把s_len中每个字符作为滑动窗口的起始位置都遍历到了。
采用一个dict或者hash表(如dict1)来存储words中每个word出现的次数,count记录多少个单词出现了,
采用一个dict或者hash表(shift_w)来存储s中连续区域内每个word出现的次数;word在dict1中,就把
word加入到shitf_w中,每出现一次计数值加1,count++;当shift_w[word]>dict1[word]时,即单词重复出现啦,
此时删除最先存入shift_w中的word使其计数值减一,并且count--(为了减少不必要的计算,例如:words中的word
个数w_counts大于4,w0,w1,w2,w3,w0;当word=w0时,发现shift_w[w0]=2 而dict1[w0]=1,则要删除最左边的w0,
即第一个word,此时shift_w[w0]=dict1[w0]继续移动窗口即可,因为w1,w2,w3,w0没必要重复计算;
如果word在s中出现的顺序为: w1,w2,w3,w0,w0 ,则先删除w1,w2,w3,w0后继续移动窗口
),重复上述过程,直到满足shift_w[word]<=dict1[word]时继续移动滑动窗口;当count=w_counts时,
存储窗口开始移动的坐标,并继续上述步骤......
'''
'''
You are given a string, s, and a list of words, words, that are all of the same length.
Find all starting indices of substring(s) in s that is a concatenation of each word in words
exactly once and without any intervening characters.
For example, given:
s: "barfoothefoobarman"
words: ["foo", "bar"]
You should return the indices: [0,9].
'''
class Solution(object):
def findSubstring(self,s,words):
dict1={}
res=[]
w_len=len(words[0])
for w in words:
if w in dict1:
dict1[w]+=1
else:
dict1[w]=1
for w_pos in range(0,w_len):
shift_w={}
w_count=0
for i in range(w_pos,len(s),w_len):
word=s[i:i+w_len]
if word in dict1:
if word in shift_w:
shift_w[word]+=1
else:
shift_w[word]=1
w_count+=1
while dict1[word] < shift_w[word]:
rmPos=i - w_len*(w_count-1)
rmWord=s[rmPos:rmPos+w_len]
print i ,rmWord
shift_w[rmWord]-=1
w_count-=1
else:
shift_w.clear()
w_count=0
if w_count == len(words):
res.append(i - w_len * (w_count-1))
return res
my=Solution()
s='barfooriitheriifooriibarman'
words=['foo','bar','rii']
print my.findSubstring(s,words)
Substring with Concatenation of All Words 滑动窗口方法 串联所有单词
最新推荐文章于 2021-06-13 17:12:33 发布