文学研究助手(统计单词)KMP算法

描述:

文学研究人员需要统计某篇英文小说中某些形容词的出现次数和位置。试写一个实现这一目标的文字统计系统,称为"文学研究助手"。

基本要求:

英文小说存于文本文件中。待统计的词汇集合要一次输入完毕,即统计工作必需在程序的一次运行后就全部完成。程序的输出结果是每个词出现次数和出现位置所在行的行号,格式自行设计。

KMP算法模块:

void kmp_next(const string pattern, int patternLen, int *next) {
    
    int i = 0, j = -1;

    next[i] = j; // default next[0] = -1
    while (i < patternLen) {
        while (j >= 0 && pattern[i] != pattern[j]) {	//比较常见的next数组构建; 
            
            j = next[j];
        }
            i++;
            j++;
            next[i] = j;
    }
    //for(int index = 0; index < patternLen; ++index) printf("next指针:%d \n", n       ext[index]);//可以测试一下next数组是否正确; 
    return;
}
int kmp_search(const string text, int textLen, const string pattern, int patternLen,int pos) {
    int i = pos-1, j = 0;

    // 建立一个next数组,并且声明,不然可以会程序不报错,但就是没输出; 
    int next[patternLen + 1];
    memset(next, 0x00, sizeof(next));

//    int idx = 0;
//    memset(matchIndex, 0x00, sizeof(matchIndex));

    kmp_next(pattern, patternLen, next);
	
	
    while (i < textLen) {
        while (j >= 0 && text[i] != pattern[j]) {   //这和课本上的差不多KMP算法; 
            j = next[j];
        }
        i++;
        j++;

        // a match is found
        //        if (j == patternLen) {
        //            printf("found substring at index:" + (i - patternLen));
        //            j = next[j];
        //        }
        if (j == patternLen) {
            printf("found substring at index:%d\n", (i - patternLen));
            //j = next[j];
            //matchIndex[idx++] = i - patternLen;
            return (i - patternLen);
        }
    }


    return -1;
}

全部代码展示:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef char string[1000];   //为了能够改变大小写问题,相当于c++里的string; 
int length(string a){
	int i=0;
	while(a[i]){			//构造一个计算string长度的函数 (相当与string.size()); 
		i++;
	}
	return i;
}


void kmp_next(const string pattern, int patternLen, int *next) {
    int i = 0, j = -1;

    next[i] = j; // default next[0] = -1
    while (i < patternLen) {
        while (j >= 0 && pattern[i] != pattern[j]) {	//比较常见的next数组构建; 
            
            j = next[j];
        }
        i++;
        j++;
        next[i] = j;
    }
    //for(int index = 0; index < patternLen; ++index) printf("next指针:%d \n", next[index]);//可以测试一下next数组是否正确; 
    return;
}
int kmp_search(const string text, int textLen, const string pattern, int patternLen,int pos) {
    int i = pos-1, j = 0;

    // 建立一个next数组,并且声明,不然可以会程序不报错,但就是没输出; 
    int next[patternLen + 1];
    memset(next, 0x00, sizeof(next));

//    int idx = 0;
//    memset(matchIndex, 0x00, sizeof(matchIndex));

    kmp_next(pattern, patternLen, next);
	
	
    while (i < textLen) {
        while (j >= 0 && text[i] != pattern[j]) {   //这和课本上的差不多KMP算法; 
            j = next[j];
        }
        i++;
        j++;

        // a match is found
        //        if (j == patternLen) {
        //            printf("found substring at index:" + (i - patternLen));
        //            j = next[j];
        //        }
        if (j == patternLen) {
            printf("found substring at index:%d\n", (i - patternLen));
            //j = next[j];
            //matchIndex[idx++] = i - patternLen;
            return (i - patternLen);
        }
    }


    return -1;
}
void find(char name[],string keys){
	string text;
	int text_length; 
	int line=1;  	//行 
	int findkmp;  // 记录这一行的第几个; 
	int count=0;  //计数 (一共有多少个单词) 
	FILE *fp;
 	fp=fopen(name,"r");
	if(fp==NULL){
		printf("文件打开失败");
		exit(0);//return 一样的; 
	}
	int key_length=length(keys);
	while(!feof(fp)){  
		fgets(text,1000,fp);
		text_length=length(text);
		for(int i=0;i<text_length;i++){
			if(text[i]>='A'&&text[i]<='Z'){		//转化单词的大小写,把大写转化,以免遗漏; 
			text[i]='a'+text[i]-'A';
			}
		}
		findkmp=kmp_search(text,text_length,keys,key_length,1); //开始的位置是第一个; 
		if(findkmp==-1){
			continue;
		}else{
			count++;
			printf("row=%d,col=%d",line,findkmp);
		}
		while(findkmp!=-1){
			findkmp=kmp_search(text,text_length,keys,key_length,findkmp+2); //找到后,每次从findkmp+1开始;因为上面函数会有findkmp=findkmp-1; 
			if(findkmp!=-1){
				count++;
				printf("row=%d,col=%d",line,findkmp);//这些可以自己去美化; 
			}
		}
		line++;	
	}
	fclose(fp);
	if(count){
		printf("%s一共有%d",keys,count);
	}else{
		printf("没有找到该单词");
	}
	return;
}
void jiemian(){
	printf("1.查询单词\n");  //界面设计就不太麻烦,想美观可以自己去找; 
	printf("0.退出\n"); 
} 
int main(){
	/*int ret=0;
	string pattern;
	string text;
	scanf("%s",text);
	
	scanf("%s",pattern);
	int n=length(pattern);
	int n1=length(text);
	for(int i=0;i<n1;i++){
		if(text[i]>='A'&&text[i]<='Z'){
			text[i]='a'+text[i]-'A';
		}
	}
	//kmp_next(pattern,n,next);
	ret=kmp_search(text,n1,pattern,n,4);
	printf("%d",ret);*/
	printf("输入文件名\n"); 
	
	
	char name[20];
	gets(name); 
	while(1){
		jiemian();
		int shuru;
		scanf("%d",&shuru);
		if(shuru==1){
			printf("请输入要查询的单词\n"); 
			string keys;
			scanf("%s",keys);
			find(name,keys);   //注意这个输入的文件名,最好查询的文件在同一个文件夹里,直接输入名字加后缀如:
								//英语短篇小说.txt; 
			printf("\n");	
		}
		if(shuru==0){
			break;
		}
	}
	return 0;
}

运行案例:

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值