字符串的后缀数组

来源:互联网 发布:修改js中的字体颜色 编辑:程序博客网 时间:2024/05/02 00:35

问题

今天看到一个编程题,题目是:给定一个字符串,求出其最长的重复子串。例如输入”abczzacbca”,那么应该输出”bc”;输入”canffcancd”,输出”can”。 首先想到的是,对于字符串中的每个字符遍历,对于每个字符找到最大的重复出现的子串。然后取最大的那个。然而看到下面提示说可以使用后缀数组,搜索了一下字符串的后缀数组,总结一下!

后缀数组

在字符串处理当中,后缀树和后缀数组都是非常有力的工具。其实后缀数组是后缀树的一个非常精巧的替代品,它比后缀树容易编程实现,能够实现后缀树的很多功能而时间复杂度也不太逊色,并且,它比后缀树所占用的空间小很多。

基本定义

子串

子串比较好理解,子串就是字符串s的一个子串,用s[i..j] i<=j表示,表示字符串s的从i到j之间的子串.

后缀

后缀是说从第i个位置,到字符串s结束的一个s的子串.用suffix(i)标识,suffix(i)=s[i,s.length()].

大小比较

字符串的大小比较一般都是字典序比较.如:abc>abd,abcd>abc

后缀数组

后缀数组是一个整数的一维数组,可以用SA表示,他表示[1,n],n个数的一个全排列,这个全排列满足suffix(SA[i]) < Suffix(SA[i+1]) , 1 ≤ i

名次数组

名次数组也是一个整数的一维数组,可以用Rank表示,Rank[i]表示后缀suffix(i),在所有后缀中排的名次.

解决问题

后缀数组知道怎么回事了,那么怎么用来解决遇到的问题呢?
首先,对字符串生成相应的后缀数组,然后根据后缀数组来一次检测相邻两个后缀开头的公共部分,取大的那个,遍历完后缀,就可以找到最长的重复子串.

public String longestRepeatedSubString(String str){        int len=str.length();        String[] subStrings=new String[len];        for(int i=0;i<len;i++){            subStrings[i]=str.substring(i,len);        }        for(int i=0;i<len-1;i++){            for(int j=i+1;j<len;j++){                if(subStrings[i].compareTo(subStrings[j])>0){                    String tmp= subStrings[i];                    subStrings[i]=subStrings[j];                    subStrings[j]=tmp;                }            }        }        int  max=0;        String res="";        for(int i=0;i<len-1;i++){            String str1=subStrings[i];            String str2=subStrings[i+1];            int  k=0;            while(k<str1.length()&&k<str2.length()&&str1.charAt(k)==str2.charAt(k)){                k++;            }            if(k>max){                res=str1.substring(0,k);                max=k;            }        }        return res;    }
0 0
原创粉丝点击