百度2010年笔试题解答之“求一个字符串里最长连续字串”

本文介绍了一个寻找最长连续递增子串的O(n)算法。该算法通过一次遍历输入字符串,记录并比较连续子串长度来高效找出最长递增序列。

我能想到的算法就是一个O(n)的算法,从字符串开头开始

unsigned int nMaxContinuLen = 0;
unsigned int nCurrentContinuLen = 1;
先把第一个字符加入到一个临时结果串里
 for(unsigned int i=1;inputstr[i];i++)
{
        if (inputstr[i] == inputstr[i-1] + 1)  //当前字符和前一个连续。
        {
            nCurrentContinuLen++;
            向一个临时结果串中加入当前字符;
        }
         else //当前字符和前一个已经不连续了。
        {
             if (nCurrentContinuLen > nMaxContineLen) 更新最终结果串为当前统计的临时串;
             nCurrentContinuLen = 1; //
             清空临时串,把当前字符扔临时串里重新开始统计
        }
 }
return 最终结果串


这个很好理解,你从开头开始,看下一个字符是不是跟当前字符连续,如果连续,你就把当前字符和下一个字符都扔一个缓冲里,这样持续直到遇到不连续的字符,这样一个连续字串就得到了,然后你用一个max值更新每一个得出的字串的大小,遇到比当前max大的字串就更新结果,这事就完了。绝对的O(n),扫描一遍就完事。



### 最长公共子串算法 最长公共子串(Longest Common Substring)问题是指给定两个字符串,找到它们之间存在的最长的连续子串。与最长公共子序列不同,公共子串要字符在原字符串中是连续的。 #### 动态规划方法 动态规划是一种常见的解决最长公共子串问题的方法。其基本思想是通过构建一个二维数组来记录两个字符串中匹配字符的位置,并计算出最长连续匹配长度。 以下是一个基于动态规划的实现: ```java public class LongestCommonSubstring { public static String longestCommonSubstring(String s, String t) { int m = s.length(); int n = t.length(); int maxLen = 0; int endIdx = 0; // 创建一个二维数组存储状态 int[][] dp = new int[m + 1][n + 1]; // 填充动态规划表 for (int i = 1; i <= m; i++) { for (int j = 1; j <= n; j++) { if (s.charAt(i - 1) == t.charAt(j - 1)) { dp[i][j] = dp[i - 1][j - 1] + 1; if (dp[i][j] > maxLen) { maxLen = dp[i][j]; endIdx = i - 1; } } else { dp[i][j] = 0; } } } return s.substring(endIdx - maxLen + 1, endIdx + 1); } public static void main(String[] args) { String s = "abcdefg"; String t = "adefgwgeweg"; System.out.println("最长公共子串为: " + longestCommonSubstring(s, t)); // 输出 defg } } ``` #### 算法说明 - **时间复杂度**:`O(m * n)`,其中 `m` 和 `n` 分别是两个字符串的长度。 - **空间复杂度**:`O(m * n)`,因为需要使用一个二维数组进行状态存储。 #### 改进方案 如果希望优化空间复杂度,可以将二维数组替换为一维数组。由于每个位置的状态只依赖于前一行的结果,因此只需要保留两行即可。 --- ### 滑动窗口方法 滑动窗口方法是一种不需要动态规划的替代方案,它通过逐个移动其中一个字符串并与另一个字符串比较,从而找到最长的匹配子串。 以下是滑动窗口方法的一个实现示例: ```java public class LongestCommonSubstringSlideWindow { public static String longestCommonSubstring(String s, String t) { int m = s.length(); int n = t.length(); int maxLen = 0; int startIdx = 0; for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { int len = 0; while (i + len < m && j + len < n && s.charAt(i + len) == t.charAt(j + len)) { len++; } if (len > maxLen) { maxLen = len; startIdx = i; } } } return s.substring(startIdx, startIdx + maxLen); } public static void main(String[] args) { String s = "abcdefg"; String t = "adefgwgeweg"; System.out.println("最长公共子串为: " + longestCommonSubstring(s, t)); // 输出 defg } } ``` #### 算法说明 - **时间复杂度**:`O(m * n * min(m, n))`,这比动态规划更慢,但在某些情况下可以避免额外的空间占用。 - **空间复杂度**:`O(1)`,不需要额外的存储空间。 --- ### 相关问题 1. 如何优化最长公共子串算法的空间复杂度? 2. 动态规划和滑动窗口方法在性能上有什么差异? 3. 是否存在其他高效的最长公共子串算法
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值