**输入:** s = "aba", t = "baba"
**输出:** 6
**解释:** 以下为只相差 1 个字符的 s 和 t 串的子字符串对:
(" **a** ba", " **b** aba")
(" **a** ba", "ba **b** a")
("ab **a** ", " **b** aba")
("ab **a** ", "ba **b** a")
("a **b** a", "b **a** ba")
("a **b** a", "bab **a** ")
加粗部分分别表示 s 和 t 串选出来的子字符串。
示例 2:
**输入:** s = "ab", t = "bb"
**输出:** 3
**解释:** 以下为只相差 1 个字符的 s 和 t 串的子字符串对:
(" **a** b", " **b** b")
(" **a** b", "b **b** ")
(" **ab** ", " **bb** ")
加粗部分分别表示 s 和 t 串选出来的子字符串。
示例 3:
**输入:** s = "a", t = "a"
**输出:** 0
示例 4:
**输入:** s = "abe", t = "bbc"
**输出:** 10
提示:
1 <= s.length, t.length <= 100
s 和 t 都只包含小写英文字母。
方法一:枚举
思路与算法
题目要求求出字符串 s 与字符串 t 的连续子串中只差一个字符的子串数目,我们枚举 s 与 t 的所有连续子串,然后找其中只含有差一个字符的子串对的数目即可。在实际枚举时,我们可以枚举 s 与 t 的子串的起点 i,j,并依次往后遍历,二者不同的字符个数为 diff,当我们遍历到起点开始的第 k 个字符时:
classSolution: defcountSubstrings(self, s: str, t: str) -> int: ans = 0 for i inrange(len(s)): for j inrange(len(t)): diff = 0 k = 0 while i + k < len(s) and j + k < len(t): if s[i + k] != t[j + k]: diff += 1 if diff == 1: ans += 1 elif diff > 1: break k += 1 return ans
publicclassSolution { publicintCountSubstrings(string s, string t) { int m = s.Length, n = t.Length; int ans = 0; for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { int diff = 0; for (int k = 0; i + k < m && j + k < n; k++) { diff += s[i + k] == t[j + k] ? 0 : 1; if (diff > 1) { break; } elseif (diff == 1) { ans++; } } } } return ans; } }
[sol1-C]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
intcountSubstrings(char * s, char * t) { int m = strlen(s), n = strlen(t); int ans = 0; for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { int diff = 0; for (int k = 0; i + k < m && j + k < n; k++) { diff += s[i + k] == t[j + k] ? 0 : 1; if (diff > 1) { break; } elseif (diff == 1) { ans++; } } } } return ans; }
[sol1-JavaScript]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
var countSubstrings = function(s, t) { const m = s.length, n = t.length; let ans = 0; for (let i = 0; i < m; i++) { for (let j = 0; j < n; j++) { let diff = 0; for (let k = 0; i + k < m && j + k < n; k++) { diff += s[i + k] === t[j + k] ? 0 : 1; if (diff > 1) { break; } elseif (diff === 1) { ans++; } } } } return ans; };
[sol1-Golang]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
funccountSubstrings(s, t string) (ans int) { m, n := len(s), len(t) for i := 0; i < m; i++ { for j := 0; j < n; j++ { diff := 0 for k := 0; i+k < m && j+k < n; k++ { if s[i+k] != t[j+k] { diff++ } if diff > 1 { break } elseif diff == 1 { ans++ } } } } return ans }
复杂度分析
时间复杂度:O(m \times n \times \min(m,n)),其中 m,n 分别为字符串 s 与 t 的长度。我们需要枚举 s 与 t 的起点,此时总共有 m \times n 对起点,每对起点遍历的长度最多为 \min(m,n),因此时间复杂度为 O(m \times n \times \min(m,n))。
空间复杂度:O(1)。
方法二:动态规划
思路与算法
题目要求求出字符串 s 与字符串 t 的连续子串中只差一个字符的子串对的数目,此时我们可以枚举 s 与 t 中不相等的字符对 (s[i],t[j]),并计算以 (s[i],t[j]) 构造的符合题意的子串数目即可。在实际计算时,设以字符 s[i] 与字符 t[j] 为终点且左侧连续相等的最大长度为 dpl}[i][j],设以字符 s[i] 与字符 t[j] 为终点且右侧连续相等的最大长度为 dpr}[i][j],此时以 (s[i],t[j]) 为字符对且构成只差一个字符的子串对数目为 (\textit{dpl}[i][j] + 1) \times (\textit{dpr}[i][j] + 1),此时通过枚举所有符合要求的不同的字符对 (s[i],t[j]) 即可计算出所有符合要求的字符串对的数目。