Skip to content
Merged
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
78 changes: 58 additions & 20 deletions src/dynamic_programming/is_subsequence.rs
Original file line number Diff line number Diff line change
@@ -1,33 +1,71 @@
// Given two strings str1 and str2, return true if str1 is a subsequence of str2, or false otherwise.
// A subsequence of a string is a new string that is formed from the original string
// by deleting some (can be none) of the characters without disturbing the relative
// positions of the remaining characters.
// (i.e., "ace" is a subsequence of "abcde" while "aec" is not).
pub fn is_subsequence(str1: &str, str2: &str) -> bool {
let mut it1 = 0;
let mut it2 = 0;
//! A module for checking if one string is a subsequence of another string.
//!
//! A subsequence is formed by deleting some (can be none) of the characters
//! from the original string without disturbing the relative positions of the
//! remaining characters. This module provides a function to determine if
//! a given string is a subsequence of another string.
let byte1 = str1.as_bytes();
let byte2 = str2.as_bytes();
/// Checks if `sub` is a subsequence of `main`.
///
/// # Arguments
///
/// * `sub` - A string slice that may be a subsequence.
/// * `main` - A string slice that is checked against.
///
/// # Returns
///
/// Returns `true` if `sub` is a subsequence of `main`, otherwise returns `false`.
pub fn is_subsequence(sub: &str, main: &str) -> bool {
let mut sub_iter = sub.chars().peekable();
let mut main_iter = main.chars();

while it1 < str1.len() && it2 < str2.len() {
if byte1[it1] == byte2[it2] {
it1 += 1;
while let Some(&sub_char) = sub_iter.peek() {
match main_iter.next() {
Some(main_char) if main_char == sub_char => {
sub_iter.next();
}
None => return false,
_ => {}
}

it2 += 1;
}

it1 == str1.len()
true
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test() {
assert!(is_subsequence("abc", "ahbgdc"));
assert!(!is_subsequence("axc", "ahbgdc"));
macro_rules! subsequence_tests {
($($name:ident: $test_case:expr,)*) => {
$(
#[test]
fn $name() {
let (sub, main, expected) = $test_case;
assert_eq!(is_subsequence(sub, main), expected);
}
)*
};
}

subsequence_tests! {
test_empty_subsequence: ("", "ahbgdc", true),
test_empty_strings: ("", "", true),
test_non_empty_sub_empty_main: ("abc", "", false),
test_subsequence_found: ("abc", "ahbgdc", true),
test_subsequence_not_found: ("axc", "ahbgdc", false),
test_longer_sub: ("abcd", "abc", false),
test_single_character_match: ("a", "ahbgdc", true),
test_single_character_not_match: ("x", "ahbgdc", false),
test_subsequence_at_start: ("abc", "abchello", true),
test_subsequence_at_end: ("cde", "abcde", true),
test_same_characters: ("aaa", "aaaaa", true),
test_interspersed_subsequence: ("ace", "abcde", true),
test_different_chars_in_subsequence: ("aceg", "abcdef", false),
test_single_character_in_main_not_match: ("a", "b", false),
test_single_character_in_main_match: ("b", "b", true),
test_subsequence_with_special_chars: ("a1!c", "a1!bcd", true),
test_case_sensitive: ("aBc", "abc", false),
test_subsequence_with_whitespace: ("hello world", "h e l l o w o r l d", true),
}
}