四年之痒之求解最长重复子串

四年前,校园招聘,金山一道笔试题。

求一个字符串中的最长重复子串,比如:"xxxxxxzuichangzichuanyyyyyyyzuichangzichuan",最长重复子串应该是"zuichangzichuan"。

四年后,我的答案:

(function(str){
    str = str || '';
    if(str.length == 1) return str;
    var max_str_start = 0,
        max_str_end = 0,
        max_str_length = 0;
    for(var startIndex = 0, len = str.length - 1; startIndex < len && (len - startIndex -1 > max_str_length); startIndex++){
        for(var endIndex = str.length - 1; (startIndex < endIndex) && (endIndex - startIndex > max_str_length); endIndex--){
            var sub_str = str.substring(startIndex, endIndex);
            if(str.lastIndexOf(sub_str) > startIndex){
                max_str_start = startIndex;
                max_str_end = endIndex;
                max_str_length = endIndex - startIndex;
                break;
            }
        }
    }
    var max_str = str.substring(max_str_start, max_str_end);
    console.log('max string: ' + max_str + ', max string start: ' + max_str_start + ', max string end: ' + max_str_end);
    return max_str;
})("xxxxxxzuichangzichuanyyyyyyyzuichangzichuan");

思路:

定义三个变量,最大字串的开始位置startIndex,结束位置endIndex,字符串长度为len。

以最极端的情况入手,假设最大子串为字符串前(len-1)位,即

startIndex = 0, endIndex = len -1;

那么最大子串为

sub_str = str.substring(startIndex, endIndex)

然后查找原始字串中是否存在与该子串重复的子串,注意:非该子串本身

str.lastIndexOf(sub_str) > startIndex

如果不存在,endIndex向前移一位后,继续查找

endIndex--

如果存在,则跳出本次循环,即在startIndex为0的最大子串已经找到,startIndex向后移一位,并重置endIndex为len-1,继续查找。

max_str_start = startIndex;
max_str_end = endIndex;
max_str_offset = endIndex - startIndex;
startIndex++

以banana为例:

1. banan

2. bana

3. ban

4. ba

5. b

6. anan

7. ana(发现重复子串,记录位置)

之后就无需再比较了,因为当前字串已经是最长字串了,原因见黄色标记部分。

算法复杂度:

两个极端情况:1,所有字符都相同,只需查找一次;2,所有字符都不同,需查找n(n-1)/2次。

问题:

如果是找出两个字符串中最长公共子串呢?

posted @ 2012-06-29 14:03  alongg  阅读(412)  评论(0编辑  收藏  举报