问题描述
这个问题的描述相对来说比较简单,对于给定的一个string,需要求它里面最长的重复子串。
那么哪些串算是最长重复子串呢?比如说给定一个string "abc", 它所有可能的子串有"a", "b", "c", "ab", "bc", "abc"这么多种。因为要求是重复子串,则必然有重复的部分。而这个示例里没有重复的部分。针对这种情况可以说它的最长重复子串是一个空串""。
在举一个示例,比如string "aba",它的所有可能的子串则有"a", "b", "a", "ab", "ba", "aba"。在这种情况下,我们看到有两个重复的"a",除此以外则没有其他重复的子串了。因此"a",就是它的最长重复子串。
根据前面的讨论,我们发现这个问题存在几个困难点:
1. 怎么保存它所有的子串。如果所有的都保存的话,对于一个长度为n的串来说,它所有子串则有n * n个。很快就存储爆炸了。
2. 因为是只要找重复的子串,如何保存和记录重复的子串也是一个需要考虑的地方。
分析
针对前面的这几个问题我们可以这样来看。对于一个字符串里所有的子串,它们无非都是起始于字符串的索引0, 1, 2...n-1等。所以对于从各索引位置开始到字符串的结尾形成的串中我们需要求的最长子串可以通过互相比较它们之间最长公共部分求出来。
但是如果就这么盲目的去比较的话,每个元素都要和其他所有元素做一次比较。那么总体需要比较的次数为O(N * N)。相对来说时间复杂度还是有点偏高。
这个时候,如果把排序这一手法给用上来的话,会带来一个更好的效果。为什么会这么想呢?其实排序,从某种角度来说是把一组字符串按照它们相似的程度从小到大逐渐拉开了。所以在排完序的序列里,相邻的两个元素之间相似度是最接近的。这样的话每次只需要取相邻的两个序列进行比较,然后取得到的最大的那个就可以了。采用这种方式的话,它的时间复杂度相对就简化很多了。排序需要的时间复杂度为O(NlgN),后续比较的时间复杂度为O(N)。这样总体的效率得到不少的提升。
概括起来,解决这个问题的思路就是首先取各位置开头到最末尾的子串放到一个数组里。然后再对数组排序。这样最接近的元素就是相邻的两个了。然后再遍历整个序列去比较和取最长的公共子串。这样可以得到如下的代码:
import java.util.Arrays; public class LRS { // return the longest common prefix of s and t public static String lcp(String s, String t) { int n = Math.min(s.length(), t.length()); for (int i = 0; i < n; i++) { if (s.charAt(i) != t.charAt(i)) return s.substring(0, i); } return s.substring(0, n); } // return the longest repeated string in s public static String lrs(String s) { // form the N suffixes int N = s.length(); String[] suffixes = new String[N]; for (int i = 0; i < N; i++) { suffixes[i] = s.substring(i, N); } // sort them Arrays.sort(suffixes); // find longest repeated substring by comparing adjacent sorted suffixes String lrs = ""; for (int i = 0; i < N - 1; i++) { String x = lcp(suffixes[i], suffixes[i+1]); if (x.length() > lrs.length()) lrs = x; } return lrs; } }
总结
求最长重复子串里头最关键的地方就是利用排序的特性,在排序的结果里,相邻的两个元素之间相似度最接近。就好像数字一样,两个相邻的数字更接近一些。这样问题就转化为求相邻元素的最大公共子串。这种思路的转换比较巧妙。
参考材料
http://introcs.cs.princeton.edu/java/42sort/LRS.java.html
http://stackoverflow.com/questions/10355103/finding-the-longest-repeated-substring
https://en.wikipedia.org/wiki/Suffix_array
相关推荐
Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000. Java AC 版本
数据结构问题:“最长回文子串问题”(Longest Palindromic Substring),详细解法和代码实现; 数据结构问题:“最长回文子串问题”(Longest Palindromic Substring),详细解法和代码实现; 数据结构问题:“最长...
在IT领域,字符串处理是常见的任务之一,尤其是在编程语言如Java中。...在压缩包文件"longest-non-repeated-substring-master"中,可能包含了这个算法的详细实现和其他相关测试案例,可以作为学习和研究的参考。
LCS(longest common substring)算法,即最大公共子串,它是求两个字符串最长公共子串的问题。大体解法是用一个矩阵来记录两个字符串中所有位置的两个字符之间的匹配情况,若是匹配则为1,否则为0。然后求出对角线最长...
Given a string, find the length of the longest substring without repeating characters. Examples: Given "abcabcbb", the answer is "abc", which the length is 3. Given "bbbbb", the answer is "b", with...
c c语言_leetcode 0003_longest_substring_without_repeat.zip
java入门 java_leetcode题解之003_Longest_Substring_Without_Repeating
c语言入门 c语言_leetcode题解03-longest-substring-without-repeating-characters
js js_leetcode题解3-longest-substring-without-repeating-characters.js
javascript js_leetcode题解之159-longest-substring-with-at-most-two-distinct
本题涉及的核心知识点是“最长公共子串”(Longest Common Substring),这是一个经典的动态规划问题。以下将详细解析这个问题及其解决方案。 首先,我们需要理解“最长公共子串”的概念。在两个给定的字符串s1和s2...
最长重复子串(Longest Repeated Substring, LRS)问题是计算机科学中字符串处理领域的一个经典问题,广泛应用于数据压缩、数据挖掘、生物信息学等多个领域。随着对DNA序列分析需求的增长,寻找序列中的重复模式变得...
java java_leetcode题解之Longest Substring Without Repeating
Given a string, find the length of the longest substring without repeating characters. Examples: Given "abcabcbb", the answer is "abc", which the length is 3. Given "bbbbb", the answer is "b", with...
Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000. Example: Input: "babad" Output: "bab" Note: "aba" is also a valid answer. ...
java java_leetcode题解之Longest Substring with At Most Two Distinct
答案LeetCode-Longest_Substring_Without_Repeating_Characters 这是LeetCode上“最长子串无重复字符”问题的解决方案。 问题描述:给定一个字符串,求没有重复字符的最长子串的长度。 示例 1:输入:“abcabcbb” ...
Longest-Palindromic-Substring(最长回文子串) 给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。 Sample 1 输入: "babad" 输出: "bab" 注意: "aba" 也是一个有效答案。 Sample 2 输入...
最长公共子字符串共有两种解决方法,下面具体说说我的思路方法一:Longest Common Substring和Longest Common Subsequence是有区别的X = <a>Y = <a>X和Y的Longest Common Sequence为,长度为4X和Y的Longest Common ...
LeetCode-3.Longest_Substring_Without_Repeating_Characters 给定一个字符串,找出没有重复字符的最长子字符串的长度。 示例 1: 输入:“abcabcbb” 输出:3 解释:答案是“abc”,长度为 3。 解决方案 Python3:...