-
Notifications
You must be signed in to change notification settings - Fork 0
/
5.longest-palindromic-substring.py
187 lines (159 loc) · 5.92 KB
/
5.longest-palindromic-substring.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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
5. 最长回文子串
https://leetcode.cn/problems/longest-palindromic-substring/description/
中等
给你一个字符串 s,找到 s 中最长的回文子串。
如果字符串的反序与原始字符串相同,则该字符串称为回文字符串。
示例 1:
输入:s = "babad"
输出:"bab"
解释:"aba" 同样是符合题意的答案。
示例 2:
输入:s = "cbbd"
输出:"bb"
# 竟然没修改,一次过了,纪念一下,🎉
###################################################################
class Solution:
def longestPalindrome(self, s: str) -> str:
length = len(s)
max_substring = ''
for i in range(length):
max_substring = max(self.isPalindromic(s, i, i, length), self.isPalindromic(s, i, i + 1, length), max_substring, key=len)
return max_substring
def isPalindromic(self, s, left, right, length):
while left >=0 and right < length and s[left]==s[right]:
left -= 1
right += 1
return s[left+1:right]
###################################################################
https://segmentfault.com/a/1190000008484167
"""
若center的回文串最右侧是maxRight,j是i的对称点【"|"处为maxRight位置】则
1. j 的回文串有一部分在 id 的之外, 则i的回文半径p[i] = maxRight - i
*|--j--*=center=*--i--|*
2. j 的回文串全部在 id 的里面,则p[i] = p[j], p[i]可否可越过maxRight 否,与p[j]的的回文串范围设定矛盾
|=--j--==center==--i--=|=
3. j 的回文串刚刚在 i的回文串左端重合,则p[i]可越过maxRight
|---j---==center==---i---|=
so, 1,2: P[i] 的值就等于 min(maxRight - i, P[j])
3: i >= maxRight, 从 i 开始往两侧扩展,计算出 P[i] 的值 如果更新位置后大于maxRight, maxRight和center
"""
class Solution:
def longestPalindrome(self, s: str) -> str:
s1 = '#'.join('^{}$'.format(s))
n = len(s1)
p = [0] * len(s1)
maxRight = 0
center = 0
for i in range(1, n - 1):
if i < maxRight:
p[i] = min(p[2 * center - i], maxRight - i)
while s1[i - p[i] - 1] == s1[i + p[i] + 1]:
p[i] += 1
if i + p[i] > maxRight:
center = i
maxRight = i + p[i]
max_len, center_idx = max((p[i], i) for i in range(1, n - 1))
print(max_len, center_idx )
start = (center_idx - max_len) // 2
return s[start: start + max_len]
###################################################################
## leetcode上找的其他解法
class Solution:
def longestPalindrome(self, s: str) -> str:
res = ''
for i in range(len(s)):
start = max(i - len(res)-1 , 0)
temp = s[start : i +1]
if temp == temp[::-1]:
res = temp
else:
temp = temp[1:]
if temp == temp[::-1]:
res = temp
return res
###################################################################
class Solution:
def longestPalindrome(self, s: str) -> str:
strlen = len(s)
# if length of string < 2 or s is palindrome already
if strlen < 2 or s == s[::-1]:
return s
start, maxlen = 0, 1
for i in range(strlen):
oddstart = i - maxlen - 1
evenstart = i - maxlen
odd = s[oddstart:i+1] # len(odd) = maxlen + 2
even = s[evenstart:i+1] # len(even) = maxlen + 1
#i = 2
#maxlen = 1
#start = 0
#odd = s[2-1-1:3]….bab
#even = s[1:3]…ab
if oddstart >= 0 and odd == odd[::-1]:
start = oddstart
maxlen += 2
elif evenstart >= 0 and even == even[::-1]:
start = evenstart
maxlen += 1
return s[start:start+maxlen]
###################################################################
# 这个时间太长了。。。
class Solution(object):
def longestPalindrome(self, s):
"""
:param s: str
:return: str
a b c b
a 1 0 0 0
b 1 0 1
c 1 0
b 1
"""
dp = [[False for col in range(len(s))] for row in range(len(s))]
length = 0
max_length = 0
start = 0
end = 0
while length < len(s):
i = 0
while i + length < len(s):
j = i + length
if length == 1 or length == 0:
dp[i][j] = (s[i] == s[j])
else:
dp[i][j] = dp[i+1][j-1] and (s[i] == s[j])
if dp[i][j] and max_length < length + 1:
max_length = length + 1
start = i
end = j
i += 1
length += 1
return s[start:end+1]
###################################################################
class Solution:
def expand(self, s, left, right):
while left >= 0 and right < len(s) and s[left] == s[right]:
left -= 1
right += 1
return (right - left - 2) // 2
def longestPalindrome(self, s: str) -> str:
end, start = -1, 0
s = '#' + '#'.join(list(s)) + '#'
arm_len = []
right = -1
j = -1
for i in range(len(s)):
if right >= i:
i_sym = 2 * j - i
min_arm_len = min(arm_len[i_sym], right - i)
cur_arm_len = self.expand(s, i - min_arm_len, i + min_arm_len)
else:
cur_arm_len = self.expand(s, i, i)
arm_len.append(cur_arm_len)
if i + cur_arm_len > right:
j = i
right = i + cur_arm_len
if 2 * cur_arm_len + 1 > end - start:
start = i - cur_arm_len
end = i + cur_arm_len
return s[start+1:end+1:2]