-
Notifications
You must be signed in to change notification settings - Fork 22
/
Copy path28.find-the-index-of-the-first-occurrence-in-a-string.py
110 lines (88 loc) · 2.81 KB
/
28.find-the-index-of-the-first-occurrence-in-a-string.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# Tag: Two Pointers, String, String Matching
# Time: O(M + N)
# Space: O(N)
# Ref: -
# Note: -
# Given two strings needle and haystack, return the index of the first occurrence of needle in haystack, or -1 if needle is not part of haystack.
#
# Example 1:
#
# Input: haystack = "sadbutsad", needle = "sad"
# Output: 0
# Explanation: "sad" occurs at index 0 and 6.
# The first occurrence is at index 0, so we return 0.
#
# Example 2:
#
# Input: haystack = "leetcode", needle = "leeto"
# Output: -1
# Explanation: "leeto" did not occur in "leetcode", so we return -1.
#
#
# Constraints:
#
# 1 <= haystack.length, needle.length <= 104
# haystack and needle consist of only lowercase English characters.
#
#
class Solution:
def strStr(self, haystack: str, needle: str) -> int:
n = len(haystack)
m = len(needle)
for i in range(n):
if haystack[i : i + m] == needle:
return i
return -1
class Solution:
def strStr(self, haystack: str, needle: str) -> int:
n = len(haystack)
m = len(needle)
dp = self.buildNext(needle)
match_length = 0
for i in range(n):
while match_length > 0 and haystack[i] != needle[match_length]:
match_length = dp[match_length - 1]
if haystack[i] == needle[match_length]:
match_length += 1
if match_length == m:
return i - m + 1
return -1
def buildNext(self, text: str) -> list[int]:
n = len(text)
dp = [0] * n
k = 0
for i in range(1, n):
while k > 0 and text[i] != text[k]:
k = dp[k - 1]
if text[i] == text[k]:
k += 1
dp[i] = k
return dp
class Solution:
def strStr(self, haystack: str, needle: str) -> int:
n = len(haystack)
m = len(needle)
if (m > n):
return -1
k_ascii = 256
k_buckets = 131
high_k = 1
for i in range(m - 1): # 最高位 = k ^ (m - 1)
high_k = (high_k * k_ascii) % k_buckets
needle_hash = 0
test_hash = 0
for i in range(m):
needle_hash = (needle_hash * k_ascii + ord(needle[i])) % k_buckets
test_hash = (test_hash * k_ascii + ord(haystack[i])) % k_buckets
for i in range(n - m + 1):
if test_hash == needle_hash:
found = True
for j in range(m):
if haystack[i + j] != needle[j]:
found = False
break
if found:
return i
if i + m < n:
test_hash = ((test_hash - ord(haystack[i]) * high_k) * k_ascii + ord(haystack[i + m])) % k_buckets
return -1