<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    E81086713E446D36F62B2AA2A3502B5EB155

    Java雜家

    雜七雜八。。。一家之言

    BlogJava 首頁 新隨筆 聯系 聚合 管理
      40 Posts :: 1 Stories :: 174 Comments :: 0 Trackbacks
    問題背景

    有一種簡單的網頁判重的方法,通過求兩個網頁內容的最長公共子序列(LCS)長度來判定兩個網頁的相似程度。如:
    (網頁A)老師:請用“果然”造句。
    (網頁B)學生:先吃水果,然后喝汽水……
    它們的最長公共子序列為“果然”,長度為2。注意這里的“子序列”并不要求連續。

    類似的,下面兩個網頁:
    (網頁A)老師:請用“果然”造句。
    (網頁B)學生:先吃水果,然后喝汽水,果然拉肚子……

    最長公共子序列還是“果然”,長度為2。但不難看出,由于“果然”兩個字在網頁B中也曾連續出現,第二組網頁比第一組更加“相似”。為了區分開這兩種情況的區分度,我們改用一種稱為LZW的理論。為了嚴格的敘述相似度的計算方法,我們首先定義“文本單元”。

    假定網頁用一個不包含空白字符(空格、回車換行、水平制表符)的字符串來表示。它只包含純文本,沒有標簽。在計算相似度之前,你應該首先對該字符串進行處理,劃分成一個個“文本單元”。每個文本單位可以是一個中文字、英文單詞(由一個或多個連續的半角英文字母和數字組成,正規表達式為[a-zA-Z0- 9]+)、或者一個標點符號。

    根據上述定義,同一個標點符號的全角和半角應該被作為不同的文本單元,盡管他們看起來可能很相近;每個單獨全角英文和全角數字都應該被看成一個單獨的文本單元,而連續的半角英文字母和數字應被看成一個整體。總之,全角的字符可以與中文字同等對待。

    這樣,網頁被看成文本單元序列。例如,網頁“內容?123456??web2.00#”切分出的文本單元序列為(為了顯示方便,用下劃線分隔各文本單元):
    內_容_?_1_2_345_6_?_?_web2_._00_#

    而網頁“why內容相似??1234567890,web#00”的切分結果為:
    why_內_容_相_似_?_?_1234567890_,_web_#_00

    黑體部分給出了兩個網頁的一個公共子序列。注意“內容”、“??”分別在兩個網頁中都是連續出現的文本單元。為了獎勵這種情況,LZW規定一段由連續k個文本單元組成的字符串權值為k^2。在剛才的例子中,“內容”、“??”的權值均為4。但“00”是一個數字串,應當被看成一個單獨的文本單元。所以權值僅為1。

    根據上述規則,公共子序列“內容 ?? 00”的權值為2^2+2^2+1=9。在所有可能的子序列中,這個權值是最大的。

    給定兩個網頁,求他們的LZW相似度,即所有可能的公共子序列中的最大權值。

    注意

    1) 輸入的網頁內容以GBK編碼(參見FAQ)
    2) 除了大小寫英文字母和數字之外的其他半角字符均視為標點符號。
    輸入格式

    包含兩行,分別是網頁A和B對應的字符串(不包含空白字符)。每行至少包含5個字節,最多包含200個字節。
    輸出格式

    輸出僅一行,包含一個整數,為兩個網頁的LZW相似度。
    樣例輸入

    內容?123456??web2.00#
    why內容相似??1234567890,web#00
    樣例輸出
    9


    解答:
    該題主要分兩部分,一部分就是解析成文本單元,另一部分就是LZW的實現,LZW其實是最長公共子序列算法的一個變形。

    //============================================================================
    // Name        : LZW.cpp
    // Author      : Yovn
    // Version     :
    // Copyright   : yovnchine@gmail.com
    //============================================================================

    #include 
    <iostream>
    #include 
    <string>
    #include 
    <cstring>
    using namespace std;

    void parseToLZWLine(const char* in, int inLen, char**& out, int& actualLen) {
        
    int mark=0;
        actualLen
    =0;
        out
    =new char*[inLen];

        
    for (int i=0; i<inLen; i++) {
            
    char ch=in[i];
            
    if (ch<0) {
                
    if (mark<i) {
                    out[actualLen]
    =new char[i-mark+1];
                    strncpy(out[actualLen], in
    +mark, i-mark);
                    out[actualLen][i
    -mark]='\0';
                    actualLen
    ++;
                }
                out[actualLen]
    =new char[3];
                out[actualLen][
    0]=ch;
                out[actualLen][
    1]=in[++i];
                out[actualLen][
    2]='\0';
                actualLen
    ++;

                mark
    =i+1;
            } 
    else if ((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')||(ch>='0'&&ch<='9')) {
                
    continue;
            } 
    else//only one case left
            {
                
    if (mark<i) {
                    out[actualLen]
    =new char[i-mark+1];
                    strncpy(out[actualLen], in
    +mark, i-mark);
                    out[actualLen][i
    -mark]='\0';
                    actualLen
    ++;

                }
                out[actualLen]
    =new char[2];
                out[actualLen][
    0]=ch;
                out[actualLen][
    1]='\0';
                actualLen
    ++;
                mark
    =i+1;
            }
        }
        
    if (mark<inLen) {
            out[actualLen]
    =new char[inLen-mark+1];
            strncpy(out[actualLen], in
    +mark, inLen-mark);
            out[actualLen][inLen
    -mark]='\0';
            actualLen
    ++;

        }
    }
    void printLZWStr(char** lzwStr, int lzwLen) {
        
    for (int i=0; i<lzwLen; i++) {
            printf(
    "%s", lzwStr[i]);
            
    if (i<lzwLen-1) {
                printf(
    "_");
            }
        }
        printf(
    "\n");
    }
    void freeLZWStr(char** lzwStr, int lzwLen) {
        
    for (int i=0; i<lzwLen; i++) {
            delete[] lzwStr[i];
        }
        delete[] lzwStr;
    }

    int calcLZW(char** left, int leftLen, char** right, int rightLen) {
        
    //printLZWStr(left, leftLen);
        
    //printLZWStr(right, rightLen);
        int** result=new int*[leftLen+1];
        
    int** len=new int*[leftLen+1];
        
    for (int i=0; i<=leftLen; i++) {
            result[i]
    =new int[rightLen+1];
            len[i]
    =new int[rightLen+1];
            result[i][
    0]=0;
            len[i][
    0]=0;
        }
        memset(result[
    0], 0, sizeof(int)*(rightLen+1));
        memset(len[
    0], 0, sizeof(int)*(rightLen+1));
        
    for (int i=1; i<=leftLen; i++) {
            
    for (int j=1; j<=rightLen; j++) {
                
    if (strcmp(left[i-1], right[j-1])==0) {
                    
    //back trace one

                    len[i][j]
    =len[i-1][j-1]+1;
                    result[i][j]
    =result[i-1][j-1]-(len[i-1][j-1]*len[i-1][j-1])
                            
    +(len[i][j]*len[i][j]);

                } 
    else if (result[i-1][j]>=result[i][j-1]) {
                    result[i][j]
    =result[i-1][j];
                } 
    else {
                    result[i][j]
    =result[i][j-1];
                }

            }
        }

        
    int ret= result[leftLen][rightLen];
        
    for (int i=0; i<=leftLen; i++) {
            delete[] result[i];
            delete[] len[i];

        }
        delete[] result;
        delete[] len;
        
    return ret;

    }

    int main() {
        
    char** lzwStr1=NULL;
        
    char** lzwStr2=NULL;
        string str1;
        string str2;
        
    int lzwLen1=0;
        
    int lzwLen2=0;
        getline(cin,str1);
        getline(cin,str2);
        
        parseToLZWLine(str1.c_str(), strlen(str1.c_str()), lzwStr1, lzwLen1);
        parseToLZWLine(str2.c_str(), strlen(str2.c_str()), lzwStr2, lzwLen2);

        cout
    <<calcLZW(lzwStr1, lzwLen1, lzwStr2, lzwLen2)<<endl;

        freeLZWStr(lzwStr1, lzwLen1);
        freeLZWStr(lzwStr2, lzwLen2);

        
    return 0;
    }



    posted on 2008-05-31 23:20 DoubleH 閱讀(2427) 評論(3)  編輯  收藏

    Feedback

    # re: 2008百度之星資格賽第二題——網頁判重 2008-06-01 09:23 如坐春風
    有意思、  回復  更多評論
      

    # re: 2008百度之星資格賽第二題——網頁判重 2008-06-02 13:59 BT下載
    那我http://www.5a520.cn 小說520 怎算法來定呢?  回復  更多評論
      

    # re: 2008百度之星資格賽第二題——網頁判重 2008-06-03 07:11 lang
    前不久和人討論類似的問題。
    也想到了第二種方法。
    用途是用來給網絡抓取得地理數據排重!
      回復  更多評論
      


    只有注冊用戶登錄后才能發表評論。


    網站導航:
     
    主站蜘蛛池模板: 成人免费无码大片a毛片软件 | EEUSS影院WWW在线观看免费| 亚洲精品国产V片在线观看| 久久精品国产大片免费观看| 亚洲AV无码成人专区| 久久久久亚洲?V成人无码| 1000部啪啪未满十八勿入免费| 亚洲人成自拍网站在线观看| 亚洲日韩国产精品第一页一区| 在线观看日本免费a∨视频| a高清免费毛片久久| 亚洲1区1区3区4区产品乱码芒果 | 国产男女猛烈无遮档免费视频网站| 国产精品九九久久免费视频| 亚洲免费在线视频播放| 亚洲日韩在线中文字幕第一页| 99久久99这里只有免费费精品| 亚洲阿v天堂在线2017免费 | 无忧传媒视频免费观看入口| 亚洲视频精品在线观看| 亚洲不卡无码av中文字幕| 欧美大尺寸SUV免费| 久久精品成人免费看| 色噜噜狠狠色综合免费视频| 亚洲国产成人九九综合| 亚洲乱码中文字幕久久孕妇黑人| 天天看免费高清影视| 久久国产免费观看精品3| 一级成人毛片免费观看| 久久综合久久综合亚洲| 99人中文字幕亚洲区| 亚洲色精品vr一区二区三区 | 成年在线观看免费人视频草莓| 免费无码作爱视频| 色屁屁在线观看视频免费| 亚洲人成网站在线观看播放青青| 亚洲av无码精品网站| 中文字幕日韩亚洲| 亚洲av手机在线观看| 永久免费观看的毛片的网站| 91网站免费观看|