Skip to content

Commit be6cd60

Browse files
committed
feat: add solutions to lc problem: No.1698
No.1698.Number of Distinct Substrings in a String
1 parent a403b6b commit be6cd60

File tree

4 files changed

+203
-7
lines changed

4 files changed

+203
-7
lines changed

solution/1600-1699/1694.Reformat Phone Number/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@
9797

9898
最后将所有组之间加上破折号,返回结果字符串即可。
9999

100-
时间复杂度 $O(n)$。
100+
时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为字符串长度
101101

102102
<!-- tabs:start -->
103103

solution/1600-1699/1698.Number of Distinct Substrings in a String/README.md

+109-2
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,24 @@
4242

4343
<!-- 这里可写通用的实现逻辑 -->
4444

45+
**方法一:暴力枚举**
46+
47+
枚举所有子串,使用哈希表记录不同子串的个数。
48+
49+
时间复杂度 $O(n^3)$,空间复杂度 $O(n^2)$。其中 $n$ 为字符串长度。
50+
51+
**方法二:字符串哈希**
52+
53+
**字符串哈希**是把一个任意长度的字符串映射成一个非负整数,并且其冲突的概率几乎为 0。字符串哈希用于计算字符串哈希值,快速判断两个字符串是否相等。
54+
55+
取一固定值 BASE,把字符串看作是 BASE 进制数,并分配一个大于 0 的数值,代表每种字符。一般来说,我们分配的数值都远小于 BASE。例如,对于小写字母构成的字符串,可以令 a=1, b=2, ..., z=26。取一固定值 MOD,求出该 BASE 进制对 M 的余数,作为该字符串的 hash 值。
56+
57+
一般来说,取 BASE=131 或者 BASE=13331,此时 hash 值产生的冲突概率极低。只要两个字符串 hash 值相同,我们就认为两个字符串是相等的。通常 MOD 取 2^64,C++ 里,可以直接使用 unsigned long long 类型存储这个 hash 值,在计算时不处理算术溢出问题,产生溢出时相当于自动对 2^64 取模,这样可以避免低效取模运算。
58+
59+
除了在极特殊构造的数据上,上述 hash 算法很难产生冲突,一般情况下上述 hash 算法完全可以出现在题目的标准答案中。我们还可以多取一些恰当的 BASE 和 MOD 的值(例如大质数),多进行几组 hash 运算,当结果都相同时才认为原字符串相等,就更加难以构造出使这个 hash 产生错误的数据。
60+
61+
时间复杂度 $O(n^2)$,空间复杂度 $O(n^2)$。其中 $n$ 为字符串长度。
62+
4563
<!-- tabs:start -->
4664

4765
### **Python3**
@@ -55,6 +73,25 @@ class Solution:
5573
return len({s[i:j] for i in range(n) for j in range(i + 1, n + 1)})
5674
```
5775

76+
```python
77+
class Solution:
78+
def countDistinct(self, s: str) -> int:
79+
base = 131
80+
n = len(s)
81+
p = [0] * (n + 10)
82+
h = [0] * (n + 10)
83+
p[0] = 1
84+
for i, c in enumerate(s):
85+
p[i + 1] = p[i] * base
86+
h[i + 1] = h[i] * base + ord(c)
87+
ss = set()
88+
for i in range(1, n + 1):
89+
for j in range(i, n + 1):
90+
t = h[j] - h[i - 1] * p[j - i + 1]
91+
ss.add(t)
92+
return len(ss)
93+
```
94+
5895
### **Java**
5996

6097
<!-- 这里可写当前语言的特殊实现逻辑 -->
@@ -74,6 +111,30 @@ class Solution {
74111
}
75112
```
76113

114+
```java
115+
class Solution {
116+
public int countDistinct(String s) {
117+
int base = 131;
118+
int n = s.length();
119+
long[] p = new long[n + 10];
120+
long[] h = new long[n + 10];
121+
p[0] = 1;
122+
for (int i = 0; i < n; ++i) {
123+
p[i + 1] = p[i] * base;
124+
h[i + 1] = h[i] * base + s.charAt(i);
125+
}
126+
Set<Long> ss = new HashSet<>();
127+
for (int i = 1; i <= n; ++i) {
128+
for (int j = i; j <= n; ++j) {
129+
long t = h[j] - h[i - 1] * p[j - i + 1];
130+
ss.add(t);
131+
}
132+
}
133+
return ss.size();
134+
}
135+
}
136+
```
137+
77138
### **C++**
78139

79140
```cpp
@@ -94,14 +155,60 @@ public:
94155
};
95156
```
96157
158+
```cpp
159+
class Solution {
160+
public:
161+
int countDistinct(string s) {
162+
using ull = unsigned long long;
163+
int n = s.size();
164+
ull p[n + 10];
165+
ull h[n + 10];
166+
int base = 131;
167+
p[0] = 1;
168+
for (int i = 0; i < n; ++i) {
169+
p[i + 1] = p[i] * base;
170+
h[i + 1] = h[i] * base + s[i];
171+
}
172+
unordered_set<ull> ss;
173+
for (int i = 1; i <= n; ++i) {
174+
for (int j = i; j <= n; ++j) {
175+
ss.insert(h[j] - h[i - 1] * p[j - i + 1]);
176+
}
177+
}
178+
return ss.size();
179+
}
180+
};
181+
```
182+
97183
### **Go**
98184

99185
```go
100186
func countDistinct(s string) int {
101-
ss := map[string]bool{}
187+
ss := map[string]struct{}{}
102188
for i := range s {
103189
for j := i + 1; j <= len(s); j++ {
104-
ss[s[i:j]] = true
190+
ss[s[i:j]] = struct{}{}
191+
}
192+
}
193+
return len(ss)
194+
}
195+
```
196+
197+
```go
198+
func countDistinct(s string) int {
199+
n := len(s)
200+
p := make([]int, n+10)
201+
h := make([]int, n+10)
202+
p[0] = 1
203+
base := 131
204+
for i, c := range s {
205+
p[i+1] = p[i] * base
206+
h[i+1] = h[i]*base + int(c)
207+
}
208+
ss := map[int]struct{}{}
209+
for i := 1; i <= n; i++ {
210+
for j := i; j <= n; j++ {
211+
ss[h[j]-h[i-1]*p[j-i+1]] = struct{}{}
105212
}
106213
}
107214
return len(ss)

solution/1600-1699/1698.Number of Distinct Substrings in a String/README_EN.md

+91-2
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,25 @@ class Solution:
4848
return len({s[i:j] for i in range(n) for j in range(i + 1, n + 1)})
4949
```
5050

51+
```python
52+
class Solution:
53+
def countDistinct(self, s: str) -> int:
54+
base = 131
55+
n = len(s)
56+
p = [0] * (n + 10)
57+
h = [0] * (n + 10)
58+
p[0] = 1
59+
for i, c in enumerate(s):
60+
p[i + 1] = p[i] * base
61+
h[i + 1] = h[i] * base + ord(c)
62+
ss = set()
63+
for i in range(1, n + 1):
64+
for j in range(i, n + 1):
65+
t = h[j] - h[i - 1] * p[j - i + 1]
66+
ss.add(t)
67+
return len(ss)
68+
```
69+
5170
### **Java**
5271

5372
```java
@@ -65,6 +84,30 @@ class Solution {
6584
}
6685
```
6786

87+
```java
88+
class Solution {
89+
public int countDistinct(String s) {
90+
int base = 131;
91+
int n = s.length();
92+
long[] p = new long[n + 10];
93+
long[] h = new long[n + 10];
94+
p[0] = 1;
95+
for (int i = 0; i < n; ++i) {
96+
p[i + 1] = p[i] * base;
97+
h[i + 1] = h[i] * base + s.charAt(i);
98+
}
99+
Set<Long> ss = new HashSet<>();
100+
for (int i = 1; i <= n; ++i) {
101+
for (int j = i; j <= n; ++j) {
102+
long t = h[j] - h[i - 1] * p[j - i + 1];
103+
ss.add(t);
104+
}
105+
}
106+
return ss.size();
107+
}
108+
}
109+
```
110+
68111
### **C++**
69112

70113
```cpp
@@ -85,14 +128,60 @@ public:
85128
};
86129
```
87130
131+
```cpp
132+
class Solution {
133+
public:
134+
int countDistinct(string s) {
135+
using ull = unsigned long long;
136+
int n = s.size();
137+
ull p[n + 10];
138+
ull h[n + 10];
139+
int base = 131;
140+
p[0] = 1;
141+
for (int i = 0; i < n; ++i) {
142+
p[i + 1] = p[i] * base;
143+
h[i + 1] = h[i] * base + s[i];
144+
}
145+
unordered_set<ull> ss;
146+
for (int i = 1; i <= n; ++i) {
147+
for (int j = i; j <= n; ++j) {
148+
ss.insert(h[j] - h[i - 1] * p[j - i + 1]);
149+
}
150+
}
151+
return ss.size();
152+
}
153+
};
154+
```
155+
88156
### **Go**
89157

90158
```go
91159
func countDistinct(s string) int {
92-
ss := map[string]bool{}
160+
ss := map[string]struct{}{}
93161
for i := range s {
94162
for j := i + 1; j <= len(s); j++ {
95-
ss[s[i:j]] = true
163+
ss[s[i:j]] = struct{}{}
164+
}
165+
}
166+
return len(ss)
167+
}
168+
```
169+
170+
```go
171+
func countDistinct(s string) int {
172+
n := len(s)
173+
p := make([]int, n+10)
174+
h := make([]int, n+10)
175+
p[0] = 1
176+
base := 131
177+
for i, c := range s {
178+
p[i+1] = p[i] * base
179+
h[i+1] = h[i]*base + int(c)
180+
}
181+
ss := map[int]struct{}{}
182+
for i := 1; i <= n; i++ {
183+
for j := i; j <= n; j++ {
184+
ss[h[j]-h[i-1]*p[j-i+1]] = struct{}{}
96185
}
97186
}
98187
return len(ss)

solution/1600-1699/1698.Number of Distinct Substrings in a String/Solution.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
func countDistinct(s string) int {
2-
ss := map[string]bool{}
2+
ss := map[string]struct{}{}
33
for i := range s {
44
for j := i + 1; j <= len(s); j++ {
5-
ss[s[i:j]] = true
5+
ss[s[i:j]] = struct{}{}
66
}
77
}
88
return len(ss)

0 commit comments

Comments
 (0)