<<编程珠玑>> 字符串

终于到了最后一章了:

(时间有点晚了,先写一部分。。。)

单词:

        十五章上来先是讲了单词也就是包含在空白中的字符串的排序统计,作者先是使用了C++STL,这里倍感自己这方面知识的欠缺,准备好好补补.

接下来是作者自己定义的结构体,实现了相同的功能,但是却没有排序.这个"单词的应用可以用在文本分类当中,下面直接上程序:

#include  <stdio.h>
#include  <string.h>
typedef  node* nodeptr;
typedef struct node
{
    char* word;
    int count;
    nodeptr next;
}node;
#define  NHASH  29989;
#define  MULT   31;
#define  BUFSIZE  20;//定义缓冲区长度
nodeptr bin[NHASH];
unsigned int hash(char* p);
void  inword(char*);
void  printbin();
int  main(void)
{
    char buf[BUFSIZE];
    while(sacnf("%s",buf)!=EOF)
             inword(buf);
    printbin();
    return 0;
}
unsigned int  hash(char* p)
{
     if(p==NULL)
        exit(1);
    unsigned int h=0;
    for(;*p;p++)
      h=h*MULT+(*p);
    return  h%NHASH;
}
void  inword(char* p)
{
    if(p==NULL)
        return ;
    unsigned h=hash(p);
    nodeptr p1=bin[h];
    for(;p1!=NULL;p1=p1->next)
        if(strcmp(p1->word,p)==0)
           {
               p1->count++;
               return ;
            }
    nodeptr temp=nodeptr(malloc(sizeof(node)));
    if(temp==NULL)
       exit(1);
    temp->word=char*(malloc(strlen(p)+1));
    if(temp->word==NULL)
        exit(1);
    strcpy(temp->word,p);
    temp->count=1;
    temp->next=bin[h];
    bin[h]=temp;
}
void  printbin()
{
   nodeptr p;
   for(int i=0;i<NHASH;i++)
      for(p=bin[i];p;p=p->next)
        printf("%s  %d\n",p->word,p->count);
}
上面我加了很多的判断是否为空的操作,这个在大师的书里是无所谓的,但是在我们面试的时候,千万不能少这个,否则面试官会找毛病的。

短语:

    如何在一个长字符串中搜索特定的子字符串呢?当然是使用经典的KMP算法.

    作者又提出了另外的一个小问题来引出一种强大的数据结构(后缀数组,处理关于回文的问题时很有用):给定一个文本文件作为输入,查找其中最长的重复字符串的问题:

比如:banana中最长的重复子字符串为ana

    下面介绍后缀数组:

            其实说白了后缀数组是个字符指针数组,数组中的每个元素是相应的某个字符数组中相应位上的字符的地址,因为这个地址可以看成是以该字符为起始字符直到最后一个'\0'作为终止符的子字符串的首地址,所以称为后缀数组.

           比如:针对上面的banana这个单词,形成的后缀数组为

          

char * a[MAX];
a[0]:  "banana"
a[1]:  "anana"
a[2]:   "nana"
a[3]:   “ana"
a[4]:   "na"
a[5]:    "a"
那么形成的这个后缀数组有什么用呢?

        如果安装C语言提供的strcmp函数对上述的子字符串进行排序的话,我们知道strcmp是按照从左到右的顺序对相应字符的ASC 码进行比较的,直到找到第一个不相同的位或者是其中的一个到达结束位则返回.所以如果我们按照这个函数对子字符串进行排序,在寻找最大重复子字符串的时候我们仅需要比较相邻的就可以了啊。这是因为我们仅需要证明通过使用strcmp排序之后形成的子字符串中不存在a[i]与a[i+2]有四个相同的字符,而a[i]与a[i+1]或者是a[i+1]与a[i+2]仅有三个相同的字符就行了.(这个四和三仅仅是个例子)

        假如:  a[i]:”abcde....",a[i+2]:"abcdg",这个时候满足条件,同时假设a[i+1]与a[i+2]有三个字符相同:"abc",至于a[i+1]的第四个字符要么不存在要么小于d,但是这样子的话,

a[i+1]肯定在a[i]的前面,从而矛盾了。

      这样子我们就证明了为什么这样子排序之后只需要比较相邻的子字符串了.

      下面是程序片段 帮助更好理解

#include  <stdio.h>
#include  <string.h>
#include  <stdlib.h>// the header of qsort
int  commonlength(const char*,const char*);
int  pstrcmp(const void*,const void*);
#ifndef EOF
#define  EOF -1
#endif 
#define  MAXN 50000;
char c[MAXN],*a[MAXN];
int  main(void)
{ 
    char ch;
    int  n=0;
    unsigned int maxlegth=-1;
    unsighed int  currentlegth;
    int  maxindex;
    while((ch=getchar())!=EOF)
       {
           a[n]=&c[n];
           c[n++]=ch;
        }
    c[n]='\0';
    qsort(a,n,sizeof(char*),pstrcmp);        
    for(int i=0;i<n;i++)
     {
         currentlegth=commonlegth(a[i],a[i+1]);
         if(currentlegth>maxlegth)
            {
                maxi=i;
                maxlegth=currentlegth;
            }
    }
    printf("%.*s",maxlegth,a[maxi];
    return 0;
}
int commonlegth(const char* p,const char* q)
{
   int i=0;
   if(p==NULL||q==NULL)
       exit(1);
   while(*p && (*p++==*q++))
        i++;
   return i;
}
int  pstrcmp(const void* p,const void* q)
{
     return  strcmp(char*(p),char*(q));
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值