返回

剖析Java&C++中的字符串轮转问题:基于KMP算法的代码讲解及学习心得

后端

算法导读:KMP算法与字符串轮转问题

在算法领域,字符串匹配问题是一个经典课题。KMP算法是解决字符串匹配问题的有力算法之一,以其高效性和广泛应用性备受青睐。在本文中,我们将利用KMP算法来解决LeetCode面试题01.09——字符串轮转问题。

LeetCode面试题01.09:字符串轮转

LeetCode面试题01.09的内容如下:

给定两个字符串s1和s2,s2是否是从s1旋转得到的呢?

比如,给定s1 = "abcdefg",s2 = "fgabcde",则返回true。

示例1:

输入:s1 = "waterbottle", s2 = "erbottlewat"
输出:true

示例2:

输入:s1 = "aa", s2 = "aba"
输出:false

提示:

  1. s1和s2的长度在[1, 10^5]范围内。
  2. s1和s2都只包含小写英文字母。

代码实现:Java、C++和Rust

为了帮助读者理解KMP算法的应用和LeetCode面试题01.09的解决方案,我们分别使用Java、C++和Rust三种语言编写代码,并对所用类和方法进行逐一解析。

Java实现:

class Solution {
    /**
     * 判断字符串s2是否是从s1旋转得到
     *
     * @param s1 字符串s1
     * @param s2 字符串s2
     * @return true:是;false:否
     */
    public boolean isRotated(String s1, String s2) {
        if (s1.length() != s2.length()) {
            return false;
        }

        String s1s1 = s1 + s1;
        return s1s1.contains(s2);
    }
}

类与方法解析:

  1. Solution类: 定义了isRotated方法,用于判断字符串s2是否是从s1旋转得到。
  2. isRotated方法: 首先判断两个字符串的长度是否相等,不相等则直接返回false。然后将s1连接两次,形成s1s1,并检查s1s1是否包含s2。如果包含,则返回true,否则返回false。

C++实现:

class Solution {
public:
    /**
     * 判断字符串s2是否是从s1旋转得到
     *
     * @param s1 字符串s1
     * @param s2 字符串s2
     * @return true:是;false:否
     */
    bool isRotated(string s1, string s2) {
        if (s1.length() != s2.length()) {
            return false;
        }

        string s1s1 = s1 + s1;
        return s1s1.find(s2) != string::npos;
    }
};

类与方法解析:

  1. Solution类: 定义了isRotated方法,用于判断字符串s2是否是从s1旋转得到。
  2. isRotated方法: 首先判断两个字符串的长度是否相等,不相等则直接返回false。然后将s1连接两次,形成s1s1,并检查s1s1是否包含s2。如果包含,则返回true,否则返回false。

Rust实现:

struct Solution;

impl Solution {
    /**
     * 判断字符串s2是否是从s1旋转得到
     *
     * @param s1 字符串s1
     * @param s2 字符串s2
     * @return true:是;false:否
     */
    pub fn is_rotated(s1: &str, s2: &str) -> bool {
        if s1.len() != s2.len() {
            return false;
        }

        let s1s1 = format!("{}{}", s1, s1);
        return s1s1.contains(s2);
    }
}

类与方法解析:

  1. Solution结构体: 定义了is_rotated方法,用于判断字符串s2是否是从s1旋转得到。
  2. is_rotated方法: 首先判断两个字符串的长度是否相等,不相等则直接返回false。然后将s1连接两次,形成s1s1,并检查s1s1是否包含s2。如果包含,则返回true,否则返回false。

编程技巧:字符串处理与算法优化

在代码实现的基础上,我们可以进一步探索编程技巧和算法优化方法,以提升代码的效率和可读性。

字符串处理:

  1. 字符串连接: 在Java和C++中,可以使用+运算符连接字符串。在Rust中,可以使用format!宏连接字符串。
  2. 字符串查找: 在Java和C++中,可以使用contains方法查找子字符串。在Rust中,可以使用contains方法查找子字符串。

算法优化:

  1. 减少不必要的判断: 在判断字符串s2是否是从s1旋转得到之前,可以先判断两个字符串的长度是否相等。如果不相等,则直接返回false,避免不必要的计算。
  2. 使用KMP算法: KMP算法是一种高效的字符串匹配算法,可以在O(n)的时间复杂度内完成匹配。如果需要更快的匹配速度,可以考虑使用KMP算法。

拓展应用:Rust语言中的字符串轮转

Rust语言提供了强大的字符串处理能力,我们可以利用这些特性来实现字符串轮转。下面是一个Rust语言实现的字符串轮转代码示例:

struct Solution;

impl Solution {
    /**
     * 字符串轮转
     *
     * @param s 字符串s
     * @return 轮转后的字符串
     */
    pub fn rotate(s: &str) -> String {
        let mut chars = s.chars();
        let first = chars.next().unwrap();
        chars.chain(std::iter::once(first)).collect()
    }
}

这个代码示例使用chars()方法将字符串转换为字符迭代器,然后使用next()方法获取第一个字符,并将其作为轮转后的字符串的最后一个字符。最后,使用chain()方法将第一个字符与剩下的字符连接起来,形成轮转后的字符串。

总结与收获

通过对LeetCode面试题01.09的分析和解决方案的讲解,我们深入理解了字符串轮转问题的解决思路,掌握了KMP算法的基本原理和应用。同时,我们还探索了Java、C++和Rust三种语言中的字符串处理技巧和算法优化方法。通过本文的学习,读者可以提升自己的算法思维和编程能力,为解决更复杂的编程问题奠定坚实的基础。