编程珠玑-第15章

本章讨论了一些字符串处理的算法

1,最长重复子串

   使用了后缀字符串的技巧

#define  MAX_TEXT_LEN 2000000
#define  FORWARD_LEN 2

int getMaxCmp(const wchar_t* p1,const wchar_t* p2)
{
    int n=0;
    while(p1[n]==p2[n])n++;
    return n;
}
wstring maxCmpText( const char* file )
{
    wchar_t* text=new wchar_t[MAX_TEXT_LEN];
    wchar_t** textp=new wchar_t*[MAX_TEXT_LEN];
    for (int i=0;i<MAX_TEXT_LEN;i++)
    {
        textp[i]=text+i;
    }
    //
    memset(text,0,MAX_TEXT_LEN*sizeof(wchar_t));
    setlocale(LC_ALL,"chs");
    FILE* f=fopen(file,"r");

    wchar_t *curPos=text;
    int len=0;
    while(fgetws(curPos,1000,f))
    {
        len+=wcslen(curPos);
        curPos=text+len;
    }
    //wprintf(L"%s",text);
    printf("长度:%d\n",len);
    std::sort(textp,textp+len,[](wchar_t* p1,wchar_t* p2){
        return wcscmp(p1,p2)<0;
    });
    int nMaxCmp=0;
    wchar_t* pMax=text;
    for (int i=0;i<len-1;i++)
    {
        int tmp=getMaxCmp(textp[i],textp[i+1]);
        if (tmp>nMaxCmp)
        {
            pMax=textp[i];
            nMaxCmp=tmp;
        }
    }
    wprintf(L"%d\n",nMaxCmp);
    wstring st(pMax,pMax+nMaxCmp);
    wprintf(L"%s\n",st.c_str());
    return L"";
}

让我们来检查一下史记中的最长子串是什么?结果如下:

果不其然,由于史记里面的<孝武本纪>基本上是摘抄<封禅书>的内容,因此最长重复子串就在<封禅书>里面

但是为什么只有171个字符呢?应该更大才对,我看了一下史记,在开始处分别是"祀其名山川"和"礼其名山川",结尾处是"则祠泰一"和"则祠太一",为什么是这样呢?既然是摘抄的,应该是一样的啊

话说回来,我很想看看原本的<孝武本纪>,看看司马迁是如何描写汉武帝的,太史公肯定有其独到的观点

2,随机文本

 书上使用单词为单位生成随机文本,我生成汉字,直接以每个字输出,算法要简单一些

 这里的重点是二分搜索和随机字符的算法,使用了前几章的习题里面的技巧:二分搜索如何搜索满足条件的第一个元素?如何在不知道元素总数的情况下随机选择一个?

   

#define  MAX_TEXT_LEN 2000000
#define  FORWARD_LEN 2

int getMaxCmp(const wchar_t* p1,const wchar_t* p2)
{
    int n=0;
    while(p1[n]==p2[n])n++;
    return n;
}
int wordCmp(const wchar_t* p1,const wchar_t* p2)
{
    for (int i=0;i<FORWARD_LEN-1;i++)
    {
        if(p1[i]!=p2[i])return p1[i]-p2[i];
    }
    return 0;
}
wstring randomText( const char* file )
{
    srand(clock());
    wchar_t* text=new wchar_t[MAX_TEXT_LEN];
    wchar_t** textp=new wchar_t*[MAX_TEXT_LEN];
    for (int i=0;i<MAX_TEXT_LEN;i++)
    {
        textp[i]=text+i;
    }
    //
    memset(text,0,MAX_TEXT_LEN*sizeof(wchar_t));
    setlocale(LC_ALL,"chs");
    FILE* f=fopen(file,"r");

    wchar_t *curPos=text;
    int len=0;
    while(fgetws(curPos,1000,f))
    {
        len+=wcslen(curPos);
        curPos=text+len;
    }
    printf("长度:%d\n",len);
    std::sort(textp,textp+len,[](wchar_t* p1,wchar_t* p2){
        return wcscmp(p1,p2)<0;
    });
    int nMaxCmp=0;
    wchar_t* pMax=text;
    for (int i=0;i<len-FOWWARD+1;i++)
    {
        int tmp=getMaxCmp(textp[i],textp[i+1]);
        if (tmp>nMaxCmp)
        {
            pMax=textp[i];
            nMaxCmp=tmp;
        }
    }
    wprintf(L"%d\n",nMaxCmp);
    wstring st(pMax,pMax+nMaxCmp);
    int maxLength=2000;
    wchar_t* randStr=new wchar_t[maxLength+1];
    randStr[maxLength]=L'\0';
    randStr[0]=L'';
    randStr[1]=L'';
     
    for(int i=0;i<maxLength-FORWARD_LEN+1;i++)
    {
        int l=0;
        int r=len-1;
        int re=-1;//搜索结果i
        while(1)
        {
            if(l==r)
            {
                if(wordCmp(randStr+i,textp[l])==0)re=l;
                break;
            }             
            int m=(l+r)/2;
            if(wordCmp(randStr+i,textp[m])<=0)r=m;
            else l=m+1;
        }
        wchar_t tmp=L' ';
        int j=1;
        while(re!=-1&&re<len&&wordCmp(textp[re],randStr+i)==0)
        {
            if(rand()%j==0&&textp[re][FORWARD_LEN-1]!=L' '&&textp[re][FORWARD_LEN-1]!=L'\n')tmp=textp[re][FORWARD_LEN-1];
            re++;
            j++;
        }
        if(tmp==L'\0')tmp=L' ';
        randStr[i+FORWARD_LEN-1]=tmp;         
    }
    wprintf(L"%s\n",randStr);
    return L"";
}

由于有太多空格和换行,我把很多空格和换行干掉了,生成的文本:

始五年,淮阴侯,左右既行阴事。而李夫人田荣如此始汤方;使安曰“我”少季札书相楚、
蔡之间行四年,夹持其後宫中,又 当见臣之。 燕、卫子曰:“赵王欲发兵尽也。秦来,
五色。反,而句戟百越王。舜。”臣,奸神可得全乎南阳,乃为太阿房君臣,功。数破灭之
宗庙,岂非真草美之意方仙神或朝,秦始。韩宣公十七年徙者务在人安邑,秦灭赵又可以为
长美女极人。风居下相攻。 灵王其次曰“道备燕饮,所置吏为沛,而能督亢竖子欣喜
。先据地?”市,带复予金作,而何如廷也。项王遂以为於兹兹益矣,是相国有作奸乃与宋
元年,颇用文德,杭,此时极亡之少傅其言也,以天五年,遂西伯阳人。”诸吕礼之,遇之
後去学者少与其子不享诸臣征巴蜀,海内其察礻必祸及八·伍子章章,无书 太守。陈,还
报劳者不胜 於边邑,问所以收下。”公子曰:“秦,高之,莫敢举有济北地。故国者年
伐吴东王信武王基者夫,破镜;离为王耳目不朝。简子将兵十年卒。 

把FORWARD_LEN改成3,保留换行符:

始皇自以为九卿尽会立,是必大矣,不疑。荀息。斡流而下报赵王以诸侯,食顷,齐桓,将
不能守也。
韩厥,厥称太子,子文王生曰:
平原君求救,其将欲移兵而去。弃女子长为陶天下服。
王者之无尽索之时,季文子奔莒,则蛮夷所侵暴乱,畏诛,死者不求何获!我真王嗣,
冠固何当?”曰:“为此药者乃‘刘’也。
汤征诸侯,昭公卒,子庄王曰:“始上数在困急之中。
太史公遭李陵既壮,杀
厉公於朝廷。
清明风居西北外国。

把FORWARD_LEN改成4:

始皇帝。其语在吕后语中。于丞相去,王乃反诛我。嗟乎,利诚乱之始也!夫秦王有连。其
居於秦,
莫如从亲以孤秦。大王命季历,明天人分际,通古今之义,则两失
之矣,
其势必不
来。至长安。
武帝立,以微眇之身,国治兵︹,可以备胡。数月而降,杀之。使弃疾为陈公,不随项
羽,故立为殷王,都朝歌。诸侯兵罢归,乃阴聚徒党及谋反者。
大馀三十二年,周致伯於秦孝公、楚悼王、越王,与城阳、琅邪负海之国
也。此
两人深相结,请案兵无攻。愿大王资馀兵,击楚,其意不厌。今秦之欲伐楚,败而亡王舟。
光惧,袭楚至邓。楚兵惧,自秦归。而楚太子商臣弑其父成王代立。帝廑崩,立沃
甲兄祖辛之子祖丁,是为缪侯,续绛侯後。十二年,彗星见

已经有点史记样子了,把FORWARD_LEN改成10的时候,由于没有这么长的重复子串,直接输出实际原文了,汗

 

 

 

   

转载于:https://www.cnblogs.com/mightofcode/archive/2012/11/26/2788403.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值