• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            FireEmissary

              C++博客 :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
              14 隨筆 :: 0 文章 :: 20 評論 :: 0 Trackbacks
             

            經(jīng)典的求公共子序列算法需要兩個(gè)序列的長度已知.而且通常用于計(jì)算字符串的公共子序列.

            我實(shí)現(xiàn)的算法針對原有的算法輸入需求解耦合,使得算法極度可適配.能用于字符串公共子序列計(jì)算和文件diff計(jì)算.理論上能用于任何具備相似特征的兩個(gè)序列的公共子序列計(jì)算.

            LCS_Calculate有三個(gè)變種:

             

            template<typename L_Iterator,typename R_Iterator,typename Container>

            LCS_Size FEtool::LCS_Calculate(L_Iterator lbeg,L_Iterator lend,  R_Iterator rbeg,R_Iterator rend,Container 
            &out);

            template
            <typename L_Iterator,typename R_Container,typename Container>

            inline LCS_Size FEtool::LCS_Calculate(L_Iterator lbeg,L_Iterator lend,  R_Container 
            const&rcontainer, Container &out);

            template
            <typename L_Container,typename R_Container,typename Container>

            inline LCS_Size FEtool::LCS_Calculate(L_Container 
            const& lcontainer,   R_Container const&rcontainer, Container &out);

            L_Iterator接受輸入迭代器. R_Iterator接受隨機(jī)迭代器. L_ContainerR_Container分別調(diào)用它們的begin()end()方法轉(zhuǎn)調(diào)用到LCS_Calculate的第一個(gè)版本.

            L_*打頭的指代比較序列中左邊那個(gè),R_*打頭的指代比較序列中右邊那個(gè).

            最后一個(gè)參數(shù)Container&out接收一個(gè)容器用來輸出序列各段相同的地方.典型的Container參數(shù)為std::deque<FEtool::SectionCommon> section;也可以為FEtool:: EmptyContainer.

            class EmptyContainer
            {
            public:
                
            void push_back(SectionCommon const&){};
                LCS_Size size()
            {return 0;}
                
            void clear(){}
            }
            ;


            如果為FEtool:: EmptyContainer參數(shù)則通過模板特化代碼選擇不計(jì)算兩段序列的相同部分。

             

            struct LCS_Compare_Trait
            {
            template
            <typename L,typename R>
            static   bool equal(L const& left, R const& right)
                    
            {
                        
            return left==right;
                    }

            }
            ;

            定義了比較算法,默認(rèn)用operator==.你可以在FEtool空間通過特化或偏特化LCS_Compare_Trait:: equal來定制它.

             

            struct SectionCommon
            {
                LCS_Size L_begin;
                LCS_Size R_begin;
                LCS_Size count;
                
            void clear(){L_begin=0;R_begin=0;count=0;}
            }
            ;

            指示兩個(gè)序列的相同部分. 比如SectionCommon:: L_begin0, SectionCommon:: R_begin10, SectionCommon::count5.就表示左邊序列從0開始的5個(gè)數(shù)據(jù),和右邊序列從10開始的5個(gè)數(shù)據(jù)都相同.

             

            LCS_Calculate內(nèi)部根據(jù)傳入?yún)?shù)優(yōu)化實(shí)現(xiàn).經(jīng)過對經(jīng)典的動(dòng)態(tài)規(guī)劃解公共子序列算法的考察發(fā)現(xiàn),外圍那個(gè)循環(huán)只需要遍歷它代表的序列一次;即左邊序列則滿足輸入迭代器即可.它要求右邊序列始終是傳入隨機(jī)迭代器.內(nèi)部計(jì)算用到的數(shù)組使用了滾動(dòng)數(shù)組(LCSArray)實(shí)現(xiàn),空間占用為右邊序列長度*2.


            LCS_Calculate
            的最后一個(gè)參數(shù)不為EmptyContainer則會(huì)計(jì)算公共子序列在左右序列中各段的順序和長度.這里L_Iterator是不是隨機(jī)訪問迭代器就會(huì)影響到性能了.L_Iterator不是隨機(jī)迭代器內(nèi)部就會(huì)用到一個(gè)動(dòng)態(tài)增長的輔助數(shù)組(TrackArrayDynamic)來做回溯; L_Iterator是隨機(jī)迭代器則直接一次申請(左序列*右序列)這么大的空間(TrackArrayStatic)來輔助回溯計(jì)算.
            而如果LCS_Calculate的最后一個(gè)參數(shù)為EmptyContainer則會(huì)選擇一個(gè)空數(shù)組(TrackArrayEmpty)實(shí)現(xiàn).TrackArrayEmpty類把所有操作展開為空操作.

            所有這些,基于模板來自動(dòng)選擇.用戶不需要指定不同的函數(shù)來優(yōu)化性能:

            template<typename L_Iterator,typename R_Iterator,typename Container/*vector<LCS_Section>*/>
            LCS_Size LCS_Calculate(L_Iterator lbeg,L_Iterator lend,
                                R_Iterator rbeg,R_Iterator rend,
                                Container 
            &out)
            {
                
            out.clear();
                detail::LCSArray array(rend
            -rbeg);
               typedef detail::SelectTrackArray
            <Container,typename std::iterator_traits<L_Iterator>::iterator_category> SelectTrack;//選擇適當(dāng)?shù)幕厮輸?shù)組
               typename SelectTrack::Array trackArr(SelectTrack::TotalRows(lbeg,lend),array.columns());//選擇適當(dāng)?shù)幕厮輸?shù)組
                LCS_Size leftSize;
                LCS_Size rightSize;
              
            for( leftSize=1;lbeg!=lend;++lbeg,++leftSize)//外層只需要是輸入迭代器就可
                    
            for( rightSize=1;rightSize<=array.columns();++rightSize)
                    
            {
                        
            if(LCS_Compare_Trait::equal(*lbeg,*(rbeg+rightSize-1))){
                            array(leftSize,rightSize)
            =array(leftSize-1,rightSize-1)+1;
                            trackArr(leftSize,rightSize)
            =0;
                        }

                        
            else if(array(leftSize-1,rightSize)>=array(leftSize,rightSize-1)){
                            array(leftSize,rightSize)
            =array(leftSize-1,rightSize);
                            trackArr(leftSize,rightSize)
            =1;
                        }

                        
            else{
                            array(leftSize,rightSize)
            =array(leftSize,rightSize-1);
                            trackArr(leftSize,rightSize)
            =-1;
                        }


                    }

                    detail::LCS_KeepTrack(trackArr,
            out);

                
            return array(leftSize-1,array.columns());

            }


            完整代碼包括測試代碼下載

            posted on 2010-03-27 19:31 FireEmissary 閱讀(2841) 評論(1)  編輯 收藏 引用

            評論

            # re: 最長公共子序列的泛型算法 2010-03-28 10:22 expter
            我覺得用c語言直接寫DP還清晰明了點(diǎn)。。。  回復(fù)  更多評論
              

            香蕉久久一区二区不卡无毒影院| 狠狠久久综合伊人不卡| 国产成人久久精品一区二区三区| 国内精品久久久久| 无码人妻久久一区二区三区蜜桃| 久久午夜无码鲁丝片秋霞| 久久精品无码一区二区无码| 狠狠色丁香婷婷综合久久来来去 | 国产精品成人精品久久久| 久久久久无码精品国产app| 蜜臀av性久久久久蜜臀aⅴ| 久久国产香蕉一区精品| 精品国产乱码久久久久久人妻| 久久精品成人免费看| 一本久久a久久精品亚洲| 久久99精品久久久久久9蜜桃 | 一本一道久久精品综合| 久久人妻少妇嫩草AV蜜桃| 国产福利电影一区二区三区久久久久成人精品综合 | 欧美久久亚洲精品| 久久99国内精品自在现线| 久久99热这里只频精品6| 精品久久久久久无码免费| 国产精品久久久久久一区二区三区| 亚洲国产精品一区二区三区久久| 国产激情久久久久影院老熟女免费| 久久66热人妻偷产精品9| 97精品伊人久久久大香线蕉| 亚洲午夜久久久| 亚洲国产成人久久笫一页| 久久久久一本毛久久久| 国产成人久久777777| 91精品无码久久久久久五月天| 精品久久久久久久无码 | 国产精品久久久久影视不卡| 久久天天躁狠狠躁夜夜网站| 久久婷婷人人澡人人爽人人爱| 久久99免费视频| 国产亚州精品女人久久久久久| 国产女人aaa级久久久级| 久久精品成人影院|