一、问题描述
给定一个字符串,求出其最长重复子串
例如:abcdabcd ,最长重复子串是 abcd
最长重复子串可以重叠
例如:abcdabcda ,这时最长重复子串是 abcda ,中间的 a 是被重叠的。
二、分析
1、直观的解法
首先检测长度为 n - 1 的字符串情况,如果不存在重复则检测 n - 2, 一直递减下去,直到 1 。
这种方法的时间复杂度是 O(N * N * N),其中包括三部分,长度纬度、根据长度检测的字符串数目、字符串检测。
2、使用后缀数组
后缀数组:例如对于字符串String str="banana"的后缀数组是a[0]="anana",a[1]="nana",a[2]="ana",a[3]="na",a[4]="a",
改进的方法是利用后缀数组:对一个字符串生成相应的后缀数组后,然后再排序,排完序依次检测相邻的两个字符串的开头公共部分。
这样的时间复杂度为:
1)生成后缀数组 O(N)
2)排序 O(NlogN*N) 最后面的 N 是因为字符串比较也是 O(N)
3)依次检测相邻的两个字符串 O(N * N)
总的时间复杂度是 O(N^2*logN)
三、java实现
分为三步:
第一步:初始化后缀数组
第二步:对后缀数组进行按字典排序
第三步:对后缀数组中相邻元素进行比较,求最长子串
public classMaxSameString {/** 比较两个相邻的字符串*/
public intsameLen(String str1,String str2){int index=0;while(index
index++;
}else{break;
}
}returnindex;
}/** 使用快速排序,对字符串按照字典顺序排列*/
public void quickSort(String[] after,int start,intend){int low=start;int high=end;
String pkey=after[low];while(low0) high--;
after[low]=after[high];while(low
after[high]=after[low];
}
after[low]=pkey;if(start
quickSort(after, low+1, end);
quickSort(after, start, low-1);
}
}/***@paramargs*/
public static voidmain(String[] args) {//TODO Auto-generated method stub
MaxSameString mss=newMaxSameString();
String src="banana";//待处理数组
String[] after=new String[src.length()-1];//后缀数组//第一步:初始化后缀数组
for(int i=0;i
after[i]=src.substring(i+1);
}//第二步:对后缀数组进行按字典排序
mss.quickSort(after, 0,after.length-1);int maxlen=0;int maxi=0;//最长字符串出现在后缀数组中的位置//第三步:对后缀数组中相邻元素进行比较,求最长子串
for(int i=0;imaxlen){
maxlen=tmp;
maxi=i;
}
}
System.out.println("Max length is "+maxlen);
}
}