1
+ """
2
+ Given a string s and a non-empty string p, find all the start indices of p's anagrams in s.
3
+
4
+ Strings consists of lowercase English letters only and the length of both strings s and p will not be larger than 20,100.
5
+
6
+ The order of output does not matter.
7
+
8
+ Example 1:
9
+
10
+ Input:
11
+ s: "cbaebabacd" p: "abc"
12
+
13
+ Output:
14
+ [0, 6]
15
+
16
+ Explanation:
17
+ The substring with start index = 0 is "cba", which is an anagram of "abc".
18
+ The substring with start index = 6 is "bac", which is an anagram of "abc".
19
+ Example 2:
20
+
21
+ Input:
22
+ s: "abab" p: "ab"
23
+
24
+ Output:
25
+ [0, 1, 2]
26
+
27
+ Explanation:
28
+ The substring with start index = 0 is "ab", which is an anagram of "ab".
29
+ The substring with start index = 1 is "ba", which is an anagram of "ab".
30
+ The substring with start index = 2 is "ab", which is an anagram of "ab".
31
+
32
+
33
+ 给定一个字符串 s 和 非空字符串 p。 找到所有 p 在 s 中的变位词,将变位词开始部分的索引添加到结果中。
34
+
35
+ 字符串包含的字符均为小写英文字母。
36
+
37
+ 结果的顺序无关紧要。
38
+
39
+
40
+ 思路:
41
+ 看到标的是个 easy .. 估计数据不会很大,直接 sorted(s[i:i+len(p)]) == sorted(p) 判断了..
42
+ 结果是 TLE。
43
+
44
+ 好吧,只能认真思考下了。
45
+
46
+ 想到的是利用动态规划,还有点回溯的味道。
47
+
48
+ 子问题为:
49
+ 当前点加上之前的点是否覆盖了全部的p。
50
+
51
+ 若全部覆盖了,则返回 i - len(p) + 1 的开始索引,同时,将 s[i - len(p) + 1] 处的字符添加到 dp 的判断点中。
52
+ 这样做可以扫描到这种情况:
53
+ s = ababab
54
+ p = ab
55
+ 循环这种。
56
+
57
+ 若没有存在于最后一个dp中,那么先判断是否有重复:
58
+ 1. 如果在 p 中,但不在上一个子问题的需求解里。
59
+ 2. 如果与最前面的一个字符发生了重复。
60
+ 3. 如果与之前的一个字符不同。
61
+ 满足这三个条件那么可以无视这个重复的字符。
62
+ 比如这样:
63
+ s = abac
64
+ p = abc
65
+
66
+ 这样相当于把重复的一个 a 忽略掉了。
67
+ 同时还要判断是否它的前一个是否一致,一致的话就不能单纯的忽略了。
68
+
69
+ s = abaac / aabc
70
+ p = abc
71
+
72
+ 没有满足的上述三个条件,那么重新复制一份原始子问题,然后将当前字符判断一下,继续下一个循环即可。
73
+
74
+ beat 99% 84ms
75
+ 测试地址:
76
+ https://leetcode.com/problems/find-all-anagrams-in-a-string/description/
77
+
78
+ """
79
+ class Solution (object ):
80
+ def findAnagrams (self , s , p ):
81
+ """
82
+ :type s: str
83
+ :type p: str
84
+ :rtype: List[int]
85
+ """
86
+
87
+ # p = sorted(p)
88
+ if not s :
89
+ return []
90
+ _p = {}
91
+
92
+ for i in p :
93
+ try :
94
+ _p [i ] += 1
95
+ except :
96
+ _p [i ] = 1
97
+
98
+ result = []
99
+
100
+ x = _p .copy ()
101
+ if s [0 ] in _p :
102
+ x [s [0 ]] -= 1
103
+ if not x [s [0 ]]:
104
+ x .pop (s [0 ])
105
+
106
+ dp = x
107
+ if not dp :
108
+ return [i for i in range (len (s )) if s [i ] == p ]
109
+
110
+ for i in range (1 , len (s )):
111
+ if s [i ] in dp :
112
+ t = dp
113
+ t [s [i ]] -= 1
114
+ if not t [s [i ]]:
115
+ t .pop (s [i ])
116
+
117
+ if not t :
118
+ result .append (i - len (p )+ 1 )
119
+ x = {}
120
+ _t = s [i - len (p )+ 1 ]
121
+ x [_t ] = 1
122
+
123
+ dp = x
124
+ else :
125
+ if s [i ] in _p and s [i ] != s [i - 1 ] and s [i ] == s [i - len (p )+ 1 ]:
126
+ continue
127
+ x = _p .copy ()
128
+ if s [i ] in x :
129
+ x [s [i ]] -= 1
130
+ if not x [s [i ]]:
131
+ x .pop (s [i ])
132
+ dp = x
133
+
134
+ return result
135
+
0 commit comments