终于到了最后一章了:
(时间有点晚了,先写一部分。。。)
单词:
十五章上来先是讲了单词也就是包含在空白中的字符串的排序统计,作者先是使用了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));
}