Skip to content

[pull] main from doocs:main #203

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,19 @@

**方法一:枚举**

枚举不同的那个字符,然后向两边扩展
我们可以枚举字符串 $s$ 和 $t$ 中不同的那个字符位置,然后分别向两边扩展,直到遇到不同的字符为止,这样就可以得到以该位置为中心的满足条件的子串对数目。我们记左边扩展的相同字符个数为 $l$,右边扩展的相同字符个数为 $r$,那么以该位置为中心的满足条件的子串对数目为 $(l + 1) \times (r + 1)$,累加到答案中即可

时间复杂度 $O(m \times n \times min(m, n))$,空间复杂度 $O(1)$。其中 $m$ 和 $n$ 分别是字符串 $s$ 和 $t$ 的长度。
枚举结束后,即可得到答案。

时间复杂度 $O(m \times n \times \min(m, n))$,空间复杂度 $O(1)$。其中 $m$ 和 $n$ 分别为字符串 $s$ 和 $t$ 的长度。

**方法二:预处理 + 枚举**

方法一中,我们每次需要分别往左右两边扩展,得出 $l$ 和 $r$ 的值。实际上,我们可以预处理出以每个位置 $(i, j)$ 结尾的最长相同后缀的长度,以及以每个位置 $(i, j)$ 开头的最长相同前缀的长度,分别记录在数组 $f$ 和 $g$ 中。

接下来,与方法一类似,我们枚举字符串 $s$ 和 $t$ 中不同的那个字符位置 $(i, j)$,那么以该位置为中心的满足条件的子串对数目为 $(f[i][j] + 1) \times (g[i + 1][j + 1] + 1)$,累加到答案中即可。

时间复杂度 $O(m \times n)$,空间复杂度 $O(m \times n)$。其中 $m$ 和 $n$ 分别为字符串 $s$ 和 $t$ 的长度。

<!-- tabs:start -->

Expand All @@ -86,15 +96,36 @@
class Solution:
def countSubstrings(self, s: str, t: str) -> int:
ans = 0
m, n = len(s), len(t)
for i, a in enumerate(s):
for j, b in enumerate(t):
if a != b:
l = r = 1
while i >= l and j >= l and s[i - l] == t[j - l]:
l = r = 0
while i > l and j > l and s[i - l - 1] == t[j - l - 1]:
l += 1
while i + r < len(s) and j + r < len(t) and s[i + r] == t[j + r]:
while i + r + 1 < m and j + r + 1 < n and s[i + r + 1] == t[j + r + 1]:
r += 1
ans += l * r
ans += (l + 1) * (r + 1)
return ans
```

```python
class Solution:
def countSubstrings(self, s: str, t: str) -> int:
ans = 0
m, n = len(s), len(t)
f = [[0] * (n + 1) for _ in range(m + 1)]
g = [[0] * (n + 1) for _ in range(m + 1)]
for i, a in enumerate(s, 1):
for j, b in enumerate(t, 1):
if a == b:
f[i][j] = f[i - 1][j - 1] + 1
for i in range(m - 1, -1, -1):
for j in range(n - 1, -1, -1):
if s[i] == t[j]:
g[i][j] = g[i + 1][j + 1] + 1
else:
ans += (f[i][j] + 1) * (g[i + 1][j + 1] + 1)
return ans
```

Expand All @@ -105,19 +136,47 @@ class Solution:
```java
class Solution {
public int countSubstrings(String s, String t) {
int m = s.length(), n = t.length();
int ans = 0;
int m = s.length(), n = t.length();
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
if (s.charAt(i) != t.charAt(j)) {
int l = 1, r = 1;
while (i - l >= 0 && j - l >= 0 && s.charAt(i - l) == t.charAt(j - l)) {
int l = 0, r = 0;
while (i - l > 0 && j - l > 0 && s.charAt(i - l - 1) == t.charAt(j - l - 1)) {
++l;
}
while (i + r < m && j + r < n && s.charAt(i + r) == t.charAt(j + r)) {
while (i + r + 1 < m && j + r + 1 < n && s.charAt(i + r + 1) == t.charAt(j + r + 1)) {
++r;
}
ans += l * r;
ans += (l + 1) * (r + 1);
}
}
}
return ans;
}
}
```

```java
class Solution {
public int countSubstrings(String s, String t) {
int ans = 0;
int m = s.length(), n = t.length();
int[][] f = new int[m + 1][n + 1];
int[][] g = new int[m + 1][n + 1];
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
if (s.charAt(i) == t.charAt(j)) {
f[i + 1][j + 1] = f[i][j] + 1;
}
}
}
for (int i = m - 1; i >= 0; --i) {
for (int j = n - 1; j >= 0; --j) {
if (s.charAt(i) == t.charAt(j)) {
g[i][j] = g[i + 1][j + 1] + 1;
} else {
ans += (f[i][j] + 1) * (g[i + 1][j + 1] + 1);
}
}
}
Expand All @@ -132,21 +191,51 @@ class Solution {
class Solution {
public:
int countSubstrings(string s, string t) {
int ans = 0;
int m = s.size(), n = t.size();
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
if (s[i] != t[j]) {
int l = 0, r = 0;
while (i - l > 0 && j - l > 0 && s[i - l - 1] == t[j - l - 1]) {
++l;
}
while (i + r + 1 < m && j + r + 1 < n && s[i + r + 1] == t[j + r + 1]) {
++r;
}
ans += (l + 1) * (r + 1);
}
}
}
return ans;
}
};
```

```cpp
class Solution {
public:
int countSubstrings(string s, string t) {
int ans = 0;
int m = s.length(), n = t.length();
int f[m + 1][n + 1];
int g[m + 1][n + 1];
memset(f, 0, sizeof(f));
memset(g, 0, sizeof(g));
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
if (s[i] == t[j]) {
continue;
f[i + 1][j + 1] = f[i][j] + 1;
}
int l = 1, r = 1;
while (i - l >= 0 && j - l >= 0 && s[i - l] == t[j - l]) {
++l;
}
while (i + r < m && j + r < n && s[i + r] == t[j + r]) {
++r;
}
}
for (int i = m - 1; i >= 0; --i) {
for (int j = n - 1; j >= 0; --j) {
if (s[i] == t[j]) {
g[i][j] = g[i + 1][j + 1] + 1;
} else {
ans += (f[i][j] + 1) * (g[i + 1][j + 1] + 1);
}
ans += l * r;
}
}
return ans;
Expand All @@ -158,17 +247,47 @@ public:

```go
func countSubstrings(s string, t string) (ans int) {
m, n := len(s), len(t)
for i, a := range s {
for j, b := range t {
if a != b {
l, r := 1, 1
for i >= l && j >= l && s[i-l] == t[j-l] {
l, r := 0, 0
for i > l && j > l && s[i-l-1] == t[j-l-1] {
l++
}
for i+r < len(s) && j+r < len(t) && s[i+r] == t[j+r] {
for i+r+1 < m && j+r+1 < n && s[i+r+1] == t[j+r+1] {
r++
}
ans += l * r
ans += (l + 1) * (r + 1)
}
}
}
return
}
```

```go
func countSubstrings(s string, t string) (ans int) {
m, n := len(s), len(t)
f := make([][]int, m+1)
g := make([][]int, m+1)
for i := range f {
f[i] = make([]int, n+1)
g[i] = make([]int, n+1)
}
for i, a := range s {
for j, b := range t {
if a == b {
f[i+1][j+1] = f[i][j] + 1
}
}
}
for i := m - 1; i >= 0; i-- {
for j := n - 1; j >= 0; j-- {
if s[i] == t[j] {
g[i][j] = g[i+1][j+1] + 1
} else {
ans += (f[i][j] + 1) * (g[i+1][j+1] + 1)
}
}
}
Expand Down
Loading