获取两个字符串之间最长公共字符串的算法(PHP)

来源:互联网 发布:淘宝超级会员专享红包 编辑:程序博客网 时间:2024/06/06 04:18

算法1:
  矩阵法
  原理:字符串1:string1='aabbccdd'  字符串2:string2='accbbcdd'
  用string1的每个字符与string2的每个字符相比较,相等写做1.不等写作0,则 如下所示:
  第一行:10000000
  第二行:10000000
  第三行:0001000
  第四行:0001000
  第五行:0110000
  第六行:0110000
  第七行:000000
  第八行:0000001
  可以看到1的对角线连起来最长的那行就是所求字符串,即加删除线的部分,可得到字符串bbc和cdd 

算法2:
  折半法:
  思想:把长串折半,比如,aabcbcb就分成aabc,abcb,bcbc,cbcb,如果没有匹配的就继续折半得到aa,ab,bc...;
如果有匹配的,那么就合并相邻的匹配的串,最后找到最大的,即如果aabc,abcb,bcbc都匹配,那么就合并出aabcbc,得到一个更常长的匹配字串.
<?php
/*
    求两个字符序列中最长的公共子序列
    首先采用二分法的方式折半获取定长字符串,依次比较,若有符合的字串则合并相邻的相符字串并跳出二分循环,最后取最长的;若没有符合的则继续折半比较
*/
$a1='abbccbdabb';
$a2='acbbcacbba';
function max_long_str($str1,$str2) {
    $s_str=strlen($str1)<=strlen($str2)?$str1:$str2;//判断长短,用短的字串折半
    $l_str=strlen($str1)<=strlen($str2)?$str2:$str1;//折半后和长的字串来比较查找   
    for($j=strlen($s_str);$j>1;$j=ceil($j/2)) {//二分循环
        for($i=0;$i<strlen($s_str)-$j+1;$i++) {//对折半后长度的字串依次比较
            $temp=substr($s_str,$i,$j);
            if(($pos=strpos($l_str,$temp))!==FALSE) {
                if((($pos-$b_pos)==1)||!isset($b_pos)) {
                    $str[$n]=substr_replace($str[$n],$temp,$k);//合并相邻
                    $k++;
                    $b_pos=$pos;
                }else{$k=0;$n++;unset($b_pos);}
            }else{$k=0;$n++;unset($b_pos);};
        }
        if(isset($str)) {//有符合则不必再折半
            break;
        }
    }
    if(count($str)>=1) {//取长的
        foreach($str as $value){
                $strr=strlen($value)>=strlen($strr)?$value:$strr;
            }
    }   
    return $strr;
}
echo max_long_str($a1,$a2);
?>

算法3:
  姑且称改进型吧,效率最高的算法:

<?


    
    
$str1 "aabcbcb"
;
    
    
$str2 "abbcbabbcbacbcbb"
;
    
    
    
//-----开始定义变量----
    
$_FSTR_     ""
//----父串----
    
$_SSTR_     ""
//----字串-----
    
$_NOWSTR_    ""
//----当前的字串----
    
$_LeftStr_    ""
//----剩余的字串-----
    
$_LeftLen_    ""
//----剩余的字符串长度----
    
$R            ""
//----最终返回的字符串-----
    
    //----以长串为父串 短串为子串---
    
if (strlen($str1) >= strlen($str2
))
    {
        
$_FSTR_ $str1
;    
        
$_SSTR_ $str2
;
    }
    else 
    {
        
$_FSTR_ $str2
;    
        
$_SSTR_ $str1
;
    }

    
//-----遍历短串----    
    
for ($i 0$i strlen($_SSTR_); $i
++)
    {
        
$_NOWSTR_ ""
//-----重置当前的字串----
            
        
$_LeftStr_ substr($_SSTR_$i);    
//----剩余的字符串----

        
$_LeftLen_ strlen($_LeftStr_);    
//----剩余字串的长度----
        
        
for ($j 0$j $_LeftLen_$j
++)
        {
            
$_NOWSTR_ .= $_LeftStr_{$j
};
            
            
//----在父串中查找字串---如果长度比保存的值长--就更新----
            
if (strpos($_FSTR_$_NOWSTR_) && strlen($_NOWSTR_) > strlen($R
))
            {
                
$R $_NOWSTR_
;
            }        
        }
    }
    

    
    print 
$R 
;
    
?> 

原创粉丝点击