求N个字符串的最大公共子串

今天在一个perl论坛上面看到了这个题目,说是微软的面试题。用javascript写了一个实现,可能效率不是很高,回去研究研究模式匹配算法先~

<script>
var s1 = "drhe123rherhert346",
s2 = "hxert32344",
n = 0, t, max_len = 0, match_hash =
{
}
,
s_loop = s1.length > s2.length ? s2 : s1,
s_test = s1.length > s2.length ? s1 : s2;
for(var i = 0; i < s_loop.length && max_len <= s_loop.length - i - 1; i ++ )
{
for(var j = 0; j < s_loop.length - i && max_len <= s_loop.length - i - j - 1; j ++ )
{
t = s_loop.slice(i, s_loop.length - j);
if(new RegExp(t, "g").test(s_test))
{
match_hash[t.length] = match_hash[t.length] ? match_hash[t.length] + "," + t : t;
if(t.length > max_len)max_len = t.length;
}
n ++ ;
}
n ++ ;
}
document.write("字串1:" + s1 + "<br>字串2:" + s2 + "<br>循环次数:" + n + "<br>最大子串:" + match_hash[max_len]);
</script>

运行结果:

字串1:drhe123rherhert346
字串2:hxert32344
循环次数:35
最大子串:ert3

上次没有说思路,这里一起说下吧:
1:先从参与匹配的N个字符串中选出长度最小的字符串。定义一个max_len用来记录公共子串长度。
2(循环一):拿长度最小的字符串开刀:分割出所有子串,如“abcd”的子串有abcd,abc,ab,abcd,bc,bcd,cd如果剩下的长度小于max_len,则没有必要再继续分割,退出循环,这句话比较难于理解,体现在下面两个外层循环的for表达式中,加粗部分
3(循环二):把上面的子串分别与剩下的参与匹配的字符串进行匹配,如果有一个不符合,跳出循环。如果都符合,则为公共子串。
4:如果有一个子串为公共子串:
把这个子串按照“长度(int)=>字符串(string)”的形式存在哈希表match_hash中;
同时记录子串中的最大长度:max_len
5:从哈希表中取出max_len的值match_hash[max_len]即为最大公共子串。

<script>
function max_match()
{
var arr = [], i = 0, n = 0, max_len = 0, t, is_match = false;
match_hash =
{
}
;
while(i < arguments.length)
{
arr[i] = arguments[i];
i ++ ;
}
arr.sort(function(a, b)
{
return a.length > b.length ? 1 : - 1;
}
);
for(var i = 0; i < arr[0].length && max_len <= arr[0].length - i - 1; i ++ )
   {
      for(var j = 0; j < arr[0].length - i && max_len <= arr[0].length - i - j - 1; j ++ )
      {
         t = arr[0].slice(i, arr[0].length - j);
for(var k = 1; k < arr.length; k ++ )
{
is_match = new RegExp(t, "g").test(arr[k]);
if( ! is_match)
break;
// 累加循环次数
            n ++ ;
}
if(is_match)
{
match_hash[t.length] = match_hash[t.length] ? match_hash[t.length] + "," + t : t;
if(t.length > max_len)max_len = t.length;
}
// 累加循环次数
n ++ ;
}
// 累加循环次数
      n ++ ;
}
   /* 返回结果 */
if(max_len > 0)
{
return "参与匹配的子串:<br>"
// 为最大公共子串着色
+ arr.join("<br>").replace(new RegExp("(" + match_hash[max_len].replace(/,/, "|") + ")", "ig"), "<font color=#FF0000><b>$1<\/b><\/font>") + "<br><br>"
+ "最大子串:" + match_hash[max_len] + "<br>"
+ "循环次数:" + n;
}
else
{
return "未找到!";
}
}
document.write(max_match("奇妙的Javascript图片放大镜", "JavaScript是个脚本编程语言", "JavaScript正在成为Ruby杀手? ", "在网站上应用的JavaScript越来越多"));
</script>

运行结果:

参与匹配的子串:
JavaScript是个脚本编程语言
奇妙的Javascript图片放大镜
在网站上应用的JavaScript越来越多
JavaScript正在成为Ruby杀手?

最大子串:cript
循环次数:117

原文地址:https://www.cnblogs.com/Leo_wl/p/1772223.html