假设我们有这样的字符串及数组:
String str="banana";
boolean flag[]=new boolean[str.length];
flag为后缀数组,用于标记子串位置
for(int i=0;i<str.length;i++)
flag[i]=i;
后缀:从某个位置i开始到整个串末尾结束的一个特殊子串
flag[i]指向字符串第i个位置起始的子串for(int i=0;i<str.length();i++)
System.out.println(""+str.substring(flag[i]));
则会输出:
banana
anana
nana
ana
na
a
也许到这里,你还什么都不知道后缀数组是干啥用的,下面就要介绍一些应用和功能
得到后缀数组来对后缀子串进行排序:
for(int i=1;i<str.length();i++){//根据字典顺序对后缀排序,起始位置存入flag数组中,使用插入排序根据字典顺序对flag重组
for(int j=i;j>0;j--){
int f=str.substring(flag[j]).compareTo(str.substring(flag[j-1]));
if(f<0){
int t=flag[j];
flag[j]=flag[j-1];
flag[j-1]=t;
}
}
}
借用之前的输出则变为:
a
ana
anana
banana
na
nana
进而可以求得最长后缀重复子串
int max=0;
int wei=-1;
for(int i=0;i<str.length();i++)
{
if(symmetry(str.substring(flag[i])))
{
if(str.substring(flag[i]).length()>max)
{
wei=i;
max=str.substring(flag[i]).length();
}
}
}
System.out.println("最长对称子串为:"+str.substring(flag[wei]));
最长对称子串为:anana
但是这样只是求得从某个位置i到最后的子串是否重叠,如果str="asdfghasddsawerix",则最长对称子串会只为"x"
下面写一个求字符串的最长对称子串的方法:
public static void maxSymmetry(String str){
int max=-1;
int start=-1;
int end=-1;
for(int i=0;i<str.length();i++){
for(int j=i+1;j<str.length();j++){
if(str.charAt(i)==str.charAt(j))
{
boolean flag=symmetry(str.substring(i,j+1));
if(j-i+1>=max)
{
start=i;
end=j+1;
max=j-i+1;
}
}
}
}
System.out.println(str.substring(start,end));
}
输入asdfghasddsawerix则会得到asddsa子串
当然这个方法还可以优化,由于时间问题,懒得弄了,后期再改进优化吧。