Given two strings s
and t
, find the number of ways you can choose a non-empty substring of s
and replace a single character by a different character such that the resulting substring is a substring of t
. In other words, find the number of substrings in s
that differ from some substring in t
by exactly one character.
For example, the underlined substrings in "computer"
and "computation"
only differ by the 'e'
/'a'
, so this is a valid way.
Return the number of substrings that satisfy the condition above.
A substring is a contiguous sequence of characters within a string.
Example 1:
Input: s = "aba", t = "baba" Output: 6 Explanation: The following are the pairs of substrings from s and t that differ by exactly 1 character: ("aba", "baba") ("aba", "baba") ("aba", "baba") ("aba", "baba") ("aba", "baba") ("aba", "baba") The underlined portions are the substrings that are chosen from s and t.Example 2:
Input: s = "ab", t = "bb" Output: 3 Explanation: The following are the pairs of substrings from s and t that differ by 1 character: ("ab", "bb") ("ab", "bb") ("ab", "bb") The underlined portions are the substrings that are chosen from s and t.
Constraints:
1 <= s.length, t.length <= 100
s
and t
consist of lowercase English letters only.This problem asks to find the number of substrings in string s
that differ by exactly one character from some substring in string t
. The solutions presented use two different approaches:
Solution 1: Enumeration and Expansion
This approach iterates through all possible pairs of characters from s
and t
. If the characters differ, it expands outwards from that pair to find the longest common prefix and suffix of the substrings surrounding the differing characters. The number of substrings differing by one character is then calculated by multiplying the lengths of the prefix and suffix plus 1 (to include the differing characters themselves).
Time Complexity Analysis (Solution 1):
The nested loops iterate through all pairs of characters in s
and t
, resulting in O(mn) iterations, where 'm' is the length of s
and 'n' is the length of t
. The inner while
loops, for finding the common prefix and suffix, have a time complexity of O(min(m,n)) in the worst case. Therefore, the overall time complexity is O(mn*min(m,n)). In practice, this will often be less than the worst-case due to the early termination of the while
loops when a mismatch is found.
Space Complexity Analysis (Solution 1):
This solution uses only a constant amount of extra space, independent of the input size. Therefore, the space complexity is O(1).
Solution 2: Dynamic Programming
This solution utilizes dynamic programming to efficiently compute the lengths of common prefixes and suffixes. Two DP tables, f
and g
, are used to store the lengths of common prefixes and suffixes, respectively. The DP tables are filled iteratively, reducing redundant calculations. The algorithm then traverses the tables, and for each pair of differing characters, it uses the corresponding values in f
and g
to calculate the number of substrings differing by one character.
Time Complexity Analysis (Solution 2):
The dynamic programming approach has a time complexity of O(mn) for filling both DP tables f
and g
. The subsequent traversal of the tables to calculate ans
takes O(mn). Thus, the overall time complexity is O(m*n).
Space Complexity Analysis (Solution 2):
The space complexity is O(m*n) due to the use of the two DP tables f
and g
, each of size (m+1) x (n+1).
Code Examples (Solution 1 and 2 in Python):
Solution 1 (Python):
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 = 0
while i > l and j > l and s[i - l - 1] == t[j - l - 1]:
l += 1
while (
i + r + 1 < m and j + r + 1 < n and s[i + r + 1] == t[j + r + 1]
):
r += 1
ans += (l + 1) * (r + 1)
return ans
Solution 2 (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
The provided code examples include solutions in Python, Java, C++, and Go. The dynamic programming solution (Solution 2) offers a significant improvement in time complexity compared to the enumeration approach (Solution 1), especially for larger input strings. The space complexity increases, however, due to the use of the DP tables. The choice of which solution to use depends on the constraints of the specific problem instance (input size and memory limits).