文本中字符串的处理
问题1:在文档中统计单词的频数。
在C++中遇到这类问题只需调用STL中的set或者map就可以很快的解决了,但是在C中需要自己实现。
#include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct node{ char *word; int count; struct node * next; }node; #define NHASH 29989 #define MULT 31 node *bin[NHASH]; unsigned int hash(char *p){ unsigned int h=0; for(;*p;p++){ h=h*MULT+*p; } return h%NHASH; } void insert_word(char *s){ unsigned int h=hash(s); node *q=bin[h]; for(;q!=NULL;q=q->next){ if(strcmp(s,q->word)==0) { q->count++; return; } } node *p=(node*)malloc(sizeof(node)); p->word=(char *)malloc(strlen(s)+1); strcpy(p->word,s); p->count=1; p->next=bin[h]; bin[h]=p; } int main(){ int i=0; for(;i<NHASH;i++){ bin[i]=NULL; } // FILE *fp=fopen("word.txt","r"); char in[10]; while(scanf("%s",in)!=EOF){ insert_word(in); } printf("mian\n"); node *p;i=0; for(;i<NHASH;i++){ for(p=bin[i];p!=NULL;p=p->next){ printf("%s %d\n",p->word,p->count); } } return 0; }
假设总共有29131个不同单词,那散列表的大小为最接近它的质数29989,同意对于26个字母来说,乘数定位31.
遇到的问题scanf("s",in)!=EOF,在linux下是按ctrl+d结束的。
散列表的插入时间比平衡搜索树的时间要短很多,但是不足是平衡搜索树中的元素始终处于有序状态,很容易找到前驱,或者按顺序输出。另外散列表缺少平衡搜索树的最坏情况保证。
问题二:文本中查找最长重复子字符串。
传统的算法如下:
View Code
#include <stdio.h> int comlen(char *p,char *q){ int i=0; while(*p&&(*p==*q)){ i++; p++; q++; } return i; } int main(){ int maxlen=-1; int i,j; char c[10]="abcdabcdd"; c[9]='\0'; int maxi=-1;int maxj=-1; int thislen=0; for(i=0;i<10;i++){ for(j=i+1;j<10;j++){ if((thislen=comlen(&c[i],&c[j]))>maxlen){ maxlen=thislen; maxi=i; maxj=j; } } } printf("%d %d\n",maxi,maxlen); return 0; }
由于这个算法匹配了所有的子字符串,所以时间复杂度为n的平方。
接下来通过后缀树数组来进行改进,改进后的时间复制度是nlogn.
View Code
#include <stdio.h> #define MAXN 100 char c[MAXN],*a[MAXN],*b[MAXN]; int Pation(char *ch[],int begin,int end){ char *s=ch[end]; int i=begin-1; int j=begin; while(j<end){ if(strcmp(ch[j],s)<0){ i++; char *s=ch[i]; ch[i]=ch[j]; ch[j]=s; } j++; } ch[end]=ch[i+1]; ch[i+1]=s; return i+1; } void Sort(char *ch[],int begin,int end){ if(begin<end){ int mid=Pation(ch,begin,end); Sort(ch,begin,mid-1); Sort(ch,mid+1,end); } } int comlen(char *p,char *q){ int i=0; while(*p&&(*p++==*q++)){ i++; } return i; } int main(){ int n=0; char ch; while((ch=getchar())!=EOF){ a[n]=&c[n]; c[n++]=ch; } c[n]='\0'; int i=0; for(;i<n-1;i++){ printf("a[%d]: %s\n",i,a[i]); } Sort(a,0,n-2); printf("after sort\n"); for(i=0;i<n-1;i++){ printf("a[%d]: %s\n",i,a[i]); } i=0; int maxi=-1; for(;i<n-1;i++){ int thislen=0; int maxlen=0; if((thislen=comlen(a[i],a[i+1]))>maxlen){ thislen=maxlen; maxi=i; } } printf("lengthest string is %d %s\n",maxlen,a[maxi]); return 0; }

浙公网安备 33010602011771号