Problem of The Day: Make String a Subsequence Using Cyclic Increments
Problem Statement

Intuition
The problem involves checking whether one string (str2) can be derived as a subsequence of another string (str1) using specific transformation rules. A character from str1 can either match directly with the corresponding character in str2 or transform to match if it cycles to the next character in a circular alphabet fashion ('z' transforms to 'a').
The intuition is to traverse both strings and leverage the transformation rules to align characters. If we can exhaust all characters in str2 by moving through str1, the answer is True.
Approach
- Use two pointers,
iandj, to traversestr1andstr2, respectively. - For each pair of characters
c1(fromstr1) andc2(fromstr2), check if:c1 == c2(direct match), or(ord(c1) + 1) % 26 == ord(c2) % 26(transformation match).
- If a match is found, increment both pointers; otherwise, move the
str1pointer (i) forward to skip unmatched characters. - If the
jpointer traverses all characters ofstr2, returnTruebecausestr2is a valid subsequence. - If not, verify the remaining unmatched portion of
str2to ensure they can all be derived via transformations. - Return
Falseif any mismatch remains.
Complexity
- Time complexity:
\(O(n)\), where \(n\) is the length of
str1. The algorithm iterates throughstr1andstr2using two pointers, ensuring a single pass throughstr1in the worst case. - Space complexity: \(O(1)\), as no additional data structures are used apart from a few variables.
Code
class Solution:
def canMakeSubsequence(self, str1: str, str2: str) -> bool:
i, j = 0, 0
while i < len(str1) and j < len(str2):
c1, c2 = str1[i], str2[j]
if str1[i] == str2[j] or ((ord(c1) + 1) % 26) == ord(c2) % 26:
i += 1
j += 1
else:
i += 1
if j == len(str2):
return True
for i in range(len(str1)):
c1, c2 = str1[i], str2[j]
if ((ord(c1) + 1) % 26) != ord(c2) % 26:
return False
return True
Editorial
Approach 2: Optimized Single Pass (Two Pointer)
class Solution:
def canMakeSubsequence(self, str1: str, str2: str) -> bool:
str2_index = 0
length_str1, length_str2 = len(str1), len(str2)
# Traverse through both strings using a for loop
for str1_index in range(length_str1):
if str2_index < length_str2 and (
str1[str1_index] == str2[str2_index]
or ord(str1[str1_index]) + 1 == ord(str2[str2_index])
or ord(str1[str1_index]) - 25 == ord(str2[str2_index])
):
# If match found, move to next character in str2
str2_index += 1
# Check if all characters in str2 were matched
return str2_index == length_str2