简体   繁体   中英

How to check whether a string is subsequent of another string using recursion in python?

Goal: So my goal is to Write a recursive function is_subsequent that, given two strings, returns whether the first string is a subsequence of the second. FOR EXAMPLE, given hac and cathartic, you should return true, but given bat and table, you should return false.

I have tried to write a code to check if one string is substring of the other. Here is my code:

def is_subsequent(str1, str2):
    x = 0
    if (all(i in str2 for i in str1)):
        x = 1
    if (x):
        return True
    else:
        return False

But it doesn't care about the order of the string. I want to write a code that that takes in account the order as mentioned in the goal. And solve it using RECURSION.

The basic idea behind recursion is that your function does two different things:

  1. If the answer is really easy, it returns the answer. (This is a "base case".)
  2. Otherwise, it figures out a way to make the problem easier, and calls itself to solve the easier version of the problem. (A function calling itself is what's meant by "recursion.")

In the case of this problem, you have two base cases:

  1. If the first string is empty, it's a subsequence of anything , so that's True .
  2. If the second string is empty (and the first string isn't), nothing can be a subsequence of it, so that's False .

Then you have two ways to make the problem easier (ie by making one or both strings smaller):

  1. If the first characters match, then the answer is the same as if you called the function on both strings minus the first letter. (That is, ac is a subsequence of artic IFF c is a subsequence of rtic .)
  2. If not, then the answer is the same as if you used the same first string but minus the first letter of the second string (That is, hac is a subsequence of cathartic IFF hac is a subsequence of athartic .)
>>> def is_subsequence(needle: str, haystack: str) -> bool:
...     if not needle:
...         return True
...     if not haystack:
...         return False
...     if needle[0] == haystack[0]:
...         return is_subsequence(needle[1:], haystack[1:])
...     return is_subsequence(needle, haystack[1:])
...
>>> is_subsequence("hac", "cathartic")
True
>>> is_subsequence("bat", "table")
False

With the way you phrased your question in regards to the logic in the code that you posted there seems to be a disconnect...

You have made it clear that making this a recursive function is a requirement but having your function use the keyword all and just checking the str1 for all of the characters in str2 would all but defeat the logic in creating a recursive function.

You could pass an extra variable and remove characters on each subsequent recursive call with a terminating statement on each pass that will give you correct output.

def is_subsequent(search, text):
    if len(text) < len(search):
        return False
    for i, c in enumerate(search):
        if c != text[i]:
            return is_subsequent(search, text[1:])
    return True

This function checks if the search string is at least as long as the text string.
If so, check each character of the search string in turn to see if it matches with the text string.
If the character ever does not match, try the function again, but from 1 place further in the text.

This up here is a helper functions which deals with trivial cases, like the subsequence being empty which will always return true, or the subsequence being bigger than the other string or the other string being empty and the subsequence not, which will always return false.

def is_subsequent(str1, str2):
    if str1 == "":
        return True
    elif str2 == "" or len(str1) > len(str2):
        return False
    else:
        return _is_subsequent(str1, str2, 0, 0)

This function here takes both strings and two pointers which always indicate the position of where you are currently comparing in both strings, alternatively you could use two substrings and always compare their first characters.

If either of the pointers reaches an index that is no longer within the bounds of the string it is time to evaluate. If the i-pointer has reached the end we return true, if not we return false.

def _is_subsequent(str1, str2, i, j):
    if i >= len(str1) or j >= len(str2):
        return i >= len(str1)
    if str1[i] == str2[j]:
        return _is_subsequent(str1, str2, i + 1, j + 1)
    else:
        return _is_subsequent(str1, str2, i, j + 1)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM