文本中字符串的处理

问题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;
}

 

 

posted on 2012-06-12 19:35  蓝色守望  阅读(261)  评论(0)    收藏  举报

导航