• <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)典的求公共子序列算法需要兩個序列的長度已知.而且通常用于計算字符串的公共子序列.

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

            LCS_Calculate有三個變種:

             

            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的第一個版本.

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

            最后一個參數(shù)Container&out接收一個容器用來輸出序列各段相同的地方.典型的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ù)則通過模板特化代碼選擇不計算兩段序列的相同部分。

             

            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;}
            }
            ;

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

             

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


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

            所有這些,基于模板來自動選擇.用戶不需要指定不同的函數(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 閱讀(2830) 評論(1)  編輯 收藏 引用

            評論

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


            只有注冊用戶登錄后才能發(fā)表評論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


            久久综合狠狠综合久久97色| 精品人妻久久久久久888| 国产成人精品久久一区二区三区| 欧美久久综合九色综合| 久久国产视屏| 久久人人爽人爽人人爽av| 国产成人精品久久亚洲| 国产精品久久久99| 免费国产99久久久香蕉| 久久国产精品一区二区| 久久精品免费观看| 精品久久久久久综合日本| 国产精品欧美久久久天天影视| 国产欧美久久一区二区| 日韩精品国产自在久久现线拍| 久久精品中文字幕久久| 国产精品va久久久久久久| 久久综合九色欧美综合狠狠| 久久经典免费视频| 精品熟女少妇AV免费久久| 久久精品人人槡人妻人人玩AV | 久久久精品一区二区三区| 热99re久久国超精品首页| 久久久久噜噜噜亚洲熟女综合| 欧美亚洲国产精品久久高清| 国产成人久久精品一区二区三区| 久久久久人妻一区二区三区vr | 久久青青草原综合伊人| 久久久久久久亚洲精品| 久久香综合精品久久伊人| 久久精品免费一区二区三区| 午夜肉伦伦影院久久精品免费看国产一区二区三区 | 久久亚洲精品无码AV红樱桃| 日韩一区二区久久久久久| 欧美精品丝袜久久久中文字幕 | 亚洲精品白浆高清久久久久久| 久久久久久午夜成人影院 | 韩国三级中文字幕hd久久精品| 久久丫忘忧草产品| 国产精品熟女福利久久AV| 亚洲AV乱码久久精品蜜桃|