我们分别有两个字符串a
和b
。 a
的长度大于或等于b
。我们必须找出最长的共同子串。如果有多个答案,那么我们必须输出b
中较早出现的子字符串(较早,因为其起始索引首先出现)。
注意:a
和b
的长度最多可达10 6 。
我尝试使用后缀数组找到最长的公共子字符串(使用quicksort对后缀进行排序)。对于有多个答案的情况,我尝试推送堆栈中所有常见的子串,这些子串等于最长公共子串的长度。
我想知道有没有更快的方法呢?
答案 0 :(得分:3)
构建字符串a$b
的{{3}},即a
与某些字符串联,例如$
字符串中没有出现,然后与{{1}连接}。 (压缩的)后缀树可以在O(| a | + | b |)时间和内存中构建,并且具有O(| a | + | b |)节点。
现在,对于每个节点,我们知道它的深度(从根开始并遍历树到该节点获得的字符串的长度)。我们还可以跟踪两个布尔量:是否在与b
对应的构建阶段访问了此节点,以及是否在与a
对应的构建阶段访问了该节点(例如,我们可能好好分别构建两棵树,然后使用预订遍历合并它们。现在,任务归结为找到在两个阶段中访问过的最深的顶点,这可以通过单个预订遍历来完成。多个答案的情况应该很容易处理。
此suffix tree包含该技术的另一个(简要)概述。
答案 1 :(得分:0)
这是最长的子串,你要找的是重复还是没有。 请仔细阅读它可能会有所帮助。 http://www.programcreek.com/2013/02/leetcode-longest-substring-without-repeating-characters-java/
答案 2 :(得分:0)
import java.util.Scanner;
public class JavaApplication8 {
public static int find(String s1,String s2){
int n = s1.length();
int m = s2.length();
int ans = 0;
int[] a = new int[m];
int b[] = new int[m];
for(int i = 0;i<n;i++){
for(int j = 0;j<m;j++){
if(s1.charAt(i)==s2.charAt(j)){
if(i==0 || j==0 )a[j] = 1;
else{
a[j] = b[j-1] + 1;
}
ans = Math.max(ans, a[j]);
}
}
int[] c = a;
a = b;
b = c;
}
return ans;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String s1 = sc.next();
String s2 = sc.next();
System.out.println(find(s1,s2));
}
}
Time Complexity O(N)
Space Complexity O(N)
答案 3 :(得分:0)
package main
import (
"fmt"
"strings"
)
func main(){
fmt.Println(lcs("CLCL","LCLC"))
}
func lcs(s1,s2 string)(max int,str string){
str1 := strings.Split(s1,"")
str2 := strings.Split(s2,"")
fmt.Println(str1,str2)
str = ""
mnMatrix := [4][4]int{}
for i:=0;i<len(str1);i++{
for j:=0;j<len(str2);j++{
if str1[i]==str2[j]{
if i==0 || j==0 {
mnMatrix[i][j] = 1
max = 1
//str = str1[i]
}else{
mnMatrix[i][j] = mnMatrix[i-1][j-1]+1
max = mnMatrix[i][j]
str = ""
for k:=max;k>=1;k--{
str = str + str2[k]
//fmt.Println(str)
}
}
}else{
mnMatrix[i][j] = 0
}
}
}
fmt.Println(mnMatrix)
return max, str
}
enter code here