Skip to content

Commit 5870d78

Browse files
committed
feat: add solutions to lc problem: No.0336
No.0336.Palindrome Pairs
1 parent 35e389f commit 5870d78

File tree

3 files changed

+207
-6
lines changed

3 files changed

+207
-6
lines changed

solution/0300-0399/0336.Palindrome Pairs/README.md

Lines changed: 100 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,15 @@
4848

4949
**方法一:字符串哈希**
5050

51-
**字符串哈希**是把一个任意长度的字符串映射成一个非负整数,并且其冲突的概率几乎为 0。字符串哈希用于计算字符串哈希值,快速判断两个字符串是否相等。
51+
**字符串哈希**是把一个任意长度的字符串映射成一个非负整数,并且其冲突的概率几乎为 $0$。字符串哈希用于计算字符串哈希值,快速判断两个字符串是否相等。
5252

53-
取一固定值 BASE,把字符串看作是 BASE 进制数,并分配一个大于 0 的数值,代表每种字符。一般来说,我们分配的数值都远小于 BASE。例如,对于小写字母构成的字符串,可以令 a=1, b=2, ..., z=26。取一固定值 MOD,求出该 BASE 进制对 M 的余数,作为该字符串的 hash 值。
53+
取一固定值 $BASE$,把字符串看作是 $BASE$ 进制数,并分配一个大于 $0$ 的数值,代表每种字符。一般来说,我们分配的数值都远小于 $BASE$。例如,对于小写字母构成的字符串,可以令 $a=1$, $b=2$, ..., $z=26$。取一固定值 $MOD$,求出该 $BASE$ 进制对 $M$ 的余数,作为该字符串的 $hash$ 值。
5454

55-
一般来说,取 BASE=131 或者 BASE=13331,此时 hash 值产生的冲突概率极低。只要两个字符串 hash 值相同,我们就认为两个字符串是相等的。通常 MOD 取 2^64,C++ 里,可以直接使用 unsigned long long 类型存储这个 hash 值,在计算时不处理算术溢出问题,产生溢出时相当于自动对 2^64 取模,这样可以避免低效取模运算。
55+
一般来说,取 $BASE=131$ 或者 $BASE=13331$,此时 $hash$ 值产生的冲突概率极低。只要两个字符串 $hash$ 值相同,我们就认为两个字符串是相等的。通常 $MOD$$2^{64}$,C++ 里,可以直接使用 `unsigned long long` 类型存储这个 $hash$ 值,在计算时不处理算术溢出问题,产生溢出时相当于自动对 $2^{64}$ 取模,这样可以避免低效取模运算。
5656

57-
除了在极特殊构造的数据上,上述 hash 算法很难产生冲突,一般情况下上述 hash 算法完全可以出现在题目的标准答案中。我们还可以多取一些恰当的 BASE 和 MOD 的值(例如大质数),多进行几组 hash 运算,当结果都相同时才认为原字符串相等,就更加难以构造出使这个 hash 产生错误的数据。
57+
除了在极特殊构造的数据上,上述 $hash$ 算法很难产生冲突,一般情况下上述 $hash$ 算法完全可以出现在题目的标准答案中。我们还可以多取一些恰当的 $BASE$ 和 $MOD$ 的值(例如大质数),多进行几组 $hash$ 运算,当结果都相同时才认为原字符串相等,就更加难以构造出使这个 $hash$ 产生错误的数据。
58+
59+
**方法二:前缀树**
5860

5961
<!-- tabs:start -->
6062

@@ -63,7 +65,19 @@
6365
<!-- 这里可写当前语言的特殊实现逻辑 -->
6466

6567
```python
66-
68+
class Solution:
69+
def palindromePairs(self, words: List[str]) -> List[List[int]]:
70+
d = {w: i for i, w in enumerate(words)}
71+
ans = []
72+
for i, w in enumerate(words):
73+
for j in range(len(w) + 1):
74+
a, b = w[:j], w[j:]
75+
ra, rb = a[::-1], b[::-1]
76+
if ra in d and d[ra] != i and b == rb:
77+
ans.append([i, d[ra]])
78+
if j and rb in d and d[rb] != i and a == ra:
79+
ans.append([d[rb], i])
80+
return ans
6781
```
6882

6983
### **Java**
@@ -117,6 +131,87 @@ class Solution {
117131
}
118132
```
119133

134+
```java
135+
class Trie {
136+
Trie[] children = new Trie[26];
137+
Integer v;
138+
139+
void insert(String w, int i) {
140+
Trie node = this;
141+
for (char c : w.toCharArray()) {
142+
c -= 'a';
143+
if (node.children[c] == null) {
144+
node.children[c] = new Trie();
145+
}
146+
node = node.children[c];
147+
}
148+
node.v = i;
149+
}
150+
151+
Integer search(String w, int i, int j) {
152+
Trie node = this;
153+
for (int k = j; k >= i; --k) {
154+
int idx = w.charAt(k) - 'a';
155+
if (node.children[idx] == null) {
156+
return null;
157+
}
158+
node = node.children[idx];
159+
}
160+
return node.v;
161+
}
162+
}
163+
164+
class Solution {
165+
public List<List<Integer>> palindromePairs(String[] words) {
166+
Trie trie = new Trie();
167+
int n = words.length;
168+
for (int i = 0; i < n; ++i) {
169+
trie.insert(words[i], i);
170+
}
171+
List<List<Integer>> ans = new ArrayList<>();
172+
for (int i = 0; i < n; ++i) {
173+
String w = words[i];
174+
int m = w.length();
175+
for (int j = 0; j <= m; ++j) {
176+
if (isPalindrome(w, j, m - 1)) {
177+
Integer k = trie.search(w, 0, j - 1);
178+
if (k != null && k != i) {
179+
ans.add(Arrays.asList(i, k));
180+
}
181+
}
182+
if (j != 0 && isPalindrome(w, 0, j - 1)) {
183+
Integer k = trie.search(w, j, m - 1);
184+
if (k != null && k != i) {
185+
ans.add(Arrays.asList(k, i));
186+
}
187+
}
188+
}
189+
}
190+
return ans;
191+
}
192+
193+
// TLE
194+
// private boolean isPalindrome(String w, int i, int j) {
195+
// for (; i < j; ++i, --j) {
196+
// if (w.charAt(i) != w.charAt(j)) {
197+
// return false;
198+
// }
199+
// }
200+
// return true;
201+
// }
202+
203+
private boolean isPalindrome(String w, int start, int end) {
204+
int i = start, j = end;
205+
for (; i < j; ++i, --j) {
206+
if (w.charAt(i) != w.charAt(j)) {
207+
return false;
208+
}
209+
}
210+
return true;
211+
}
212+
}
213+
```
214+
120215
### **Go**
121216

122217
```go

solution/0300-0399/0336.Palindrome Pairs/README_EN.md

Lines changed: 94 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,19 @@
4646
### **Python3**
4747

4848
```python
49-
49+
class Solution:
50+
def palindromePairs(self, words: List[str]) -> List[List[int]]:
51+
d = {w: i for i, w in enumerate(words)}
52+
ans = []
53+
for i, w in enumerate(words):
54+
for j in range(len(w) + 1):
55+
a, b = w[:j], w[j:]
56+
ra, rb = a[::-1], b[::-1]
57+
if ra in d and d[ra] != i and b == rb:
58+
ans.append([i, d[ra]])
59+
if j and rb in d and d[rb] != i and a == ra:
60+
ans.append([d[rb], i])
61+
return ans
5062
```
5163

5264
### **Java**
@@ -98,6 +110,87 @@ class Solution {
98110
}
99111
```
100112

113+
```java
114+
class Trie {
115+
Trie[] children = new Trie[26];
116+
Integer v;
117+
118+
void insert(String w, int i) {
119+
Trie node = this;
120+
for (char c : w.toCharArray()) {
121+
c -= 'a';
122+
if (node.children[c] == null) {
123+
node.children[c] = new Trie();
124+
}
125+
node = node.children[c];
126+
}
127+
node.v = i;
128+
}
129+
130+
Integer search(String w, int i, int j) {
131+
Trie node = this;
132+
for (int k = j; k >= i; --k) {
133+
int idx = w.charAt(k) - 'a';
134+
if (node.children[idx] == null) {
135+
return null;
136+
}
137+
node = node.children[idx];
138+
}
139+
return node.v;
140+
}
141+
}
142+
143+
class Solution {
144+
public List<List<Integer>> palindromePairs(String[] words) {
145+
Trie trie = new Trie();
146+
int n = words.length;
147+
for (int i = 0; i < n; ++i) {
148+
trie.insert(words[i], i);
149+
}
150+
List<List<Integer>> ans = new ArrayList<>();
151+
for (int i = 0; i < n; ++i) {
152+
String w = words[i];
153+
int m = w.length();
154+
for (int j = 0; j <= m; ++j) {
155+
if (isPalindrome(w, j, m - 1)) {
156+
Integer k = trie.search(w, 0, j - 1);
157+
if (k != null && k != i) {
158+
ans.add(Arrays.asList(i, k));
159+
}
160+
}
161+
if (j != 0 && isPalindrome(w, 0, j - 1)) {
162+
Integer k = trie.search(w, j, m - 1);
163+
if (k != null && k != i) {
164+
ans.add(Arrays.asList(k, i));
165+
}
166+
}
167+
}
168+
}
169+
return ans;
170+
}
171+
172+
// TLE
173+
// private boolean isPalindrome(String w, int i, int j) {
174+
// for (; i < j; ++i, --j) {
175+
// if (w.charAt(i) != w.charAt(j)) {
176+
// return false;
177+
// }
178+
// }
179+
// return true;
180+
// }
181+
182+
private boolean isPalindrome(String w, int start, int end) {
183+
int i = start, j = end;
184+
for (; i < j; ++i, --j) {
185+
if (w.charAt(i) != w.charAt(j)) {
186+
return false;
187+
}
188+
}
189+
return true;
190+
}
191+
}
192+
```
193+
101194
### **Go**
102195

103196
```go
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
class Solution:
2+
def palindromePairs(self, words: List[str]) -> List[List[int]]:
3+
d = {w: i for i, w in enumerate(words)}
4+
ans = []
5+
for i, w in enumerate(words):
6+
for j in range(len(w) + 1):
7+
a, b = w[:j], w[j:]
8+
ra, rb = a[::-1], b[::-1]
9+
if ra in d and d[ra] != i and b == rb:
10+
ans.append([i, d[ra]])
11+
if j and rb in d and d[rb] != i and a == ra:
12+
ans.append([d[rb], i])
13+
return ans

0 commit comments

Comments
 (0)