题目:文学研究助手【问题描述】文学研究人员需要统计某篇英文小说中某些形容词的出现次数和位置。试写一个实现这一目标的文字统计系统,称为“文学研究助手”。【基本要求】英文小说存放于一个文本文件中。待统计的词汇集合要依次输入完毕,即统计工作必须在程序的一次运行之后就全部完成。程序的输出结果是每个词的出现次数和出现位置所在行的行号,格式自行设计。【选作内容】(1)模式匹配要基于KMP算法(2)整个统计过程中只对小说文字扫描一遍以提高效率实验完成情况:②作内容与基本要求都已完成。②附加了二个功能:算出了所查询的关键词在其出现行的具体位置和在此行出现的次数。③序共达376行。程序特色之处:A、用了KMP算法,大大提高了运算速率B、熟练且灵活地运用了链表知识C、熟练且灵活地运用了结构体知识概要设计:【抽象数据类型定义】ADT数据对象:英文字母、空格和标点符号的集合数据关系:其集合构成一篇可读性的文章基本操作:InitList(&L)操作结果:构造一个空链表;InitList_node(&L)操作结果:构造一个总链表里的分链表;copy(&T,chars)(&L)初始条件:已知chars操作结果:chars数组中的字符付给T.ch;并计算出chars的长度赋给T.lengthCreateNode(&sl,str)这个函数建立的是总链表里面的结点初始条件:已知str操作结果:建立sl结构体中某要素的节点,并将str相应值赋值给slCreateNode_node(&sl,str)这个函数建立的是总链表里面分链表的结点初始条件:已知str操作结果:建立sl结构体中某要素的节点,并将str相应值赋值给sladdnode(&ls,link)这个函数建立的是总链表初始条件:已知ls和link操作结果:将link附加到ls后面add_node(&ls,link)这个函数建立的是总链表里分链表初始条件:已知ls和link操作结果:将link附加到ls后面Index_KMP(s,t,pos)初始条件:已知字符串s,t操作结果:找出s中与t相同的开始位置IsNotCharactor(ch)初始条件:已知字符ch操作结果:判断ch是否为英文字母ShowList_node(L)初始条件:已知一个链表的头结点操作结果:将链表的中信息打印出来,并将链表的某些信息再传递下去ShowList(L)初始条件:已知L的相关信息操作结果:打印出L的相关信息find(&stringLinkList,hstrLine,row)初始条件:已知stringLinkList,hstrLine,row操作结果:在串数据链表stringLinkList,读出查找的串strkey,与传入的串hstrLine匹配如果成功将匹配的次数与行数row,写入相对应的行行数据链表Next(s,j)初始条件:已知s,j操作结果:KMP模式匹配的next函数,即找出自身匹配Count_KMP(s,t,pos)初始条件:已知字符串s和t,pos操作结果:求串t在s中出现的次数程序使用说明A.输入正确的打开文件方式,例如:h:\code.txtB.输入所要查询的单词,每输入一个单词就按回车,并最后以符号“#”结束、【程序模块调用关系】A结构体调用情况整个结构体框架主要以建立两层链表为主体。测试数据和结果用户输入统计的关键字开始读文件情况stringLinkList,stringLinkRowLink,ShowDataElemHstringRowLinkList统计情况如下:源代码:#includestdio.h#includemalloc.h#includestdlib.h#includestring.h#defineTRUE1#defineFALSE0#defineOK1#defineERROR0#defineINFEASIBLE-1#defineOVERFLOW-2#defineNULL0#defineLEN81//串的堆分配存储表示typedefstructHString{char*ch;intlength;}HString;typedefstructShowDataElem{introw;intcount;intlocation;}ShowDataElem;//行数据链表typedefstructLRowNode{ShowDataElemdata;structLRowNode*next;}LRowNode,*RowLink;typedefstruct{RowLinkhead;RowLinktail;intlen;}RowLinkList;//串数据链表typedefstructStringNode{HStringstr;RowLinkListrowlist;StringNode*next;}StringNode,*StringLink;typedefstruct{StringLinkhead,tail;intlen;}StringLinkList;//以上为定义的所需要的结构体voidcopy(HString&T,char*chars){intlen;inti;len=strlen(chars);if(!len){T.ch=NULL;T.length=0;}else{T.ch=(char*)malloc(len*sizeof(char));if(!T.ch)exit(0);for(i=0;ilen;i++)T.ch[i]=chars[i];T.ch[i]='\0';T.length=len;}}//返回子串t在主串s中第pos个字符之后的位置。intIndex(HStrings,HStringt,intpos){inti=pos;intj=1;intc;while(i=s.length&&j=t.length){if(s.ch[i-1]==t.ch[j-1])i++,j++;else{i=i-j+2;j=1;}}if(jt.length){c=i-t.length;returnc;}elsereturn0;}intNext(HStrings,intj){//KMP模式匹配的next函数if(j==1)return0;intk,i;for(k=j-1;k1;k--){for(i=1;ik;i++){if(s.ch[i-1]!=s.ch[j-k+i-1])break;}if(i==k)break;}returnk;}intIsNotCharactor(charch){//判断该字符是不是字母inta;a=ch='a'&&ch='z'||ch='A'&&ch='Z';return(!a);}intIndex_KMP(HStrings,HStringt,intpos){//KMP算法inti=pos,j=1;intc;while(i=s.length&&j=t.length){if(j==0||s.ch[i-1]==t.ch[j-1]){i++;j++;}elsej=Next(t,j);}if(jt.length&&(IsNotCharactor(s.ch[i-1])&&IsNotCharactor(s.ch[i-t.length-2]))){c=i-t.length;returnc;}elsereturn0;}intCount_KMP(HStrings,HStringt,intpos){//求t在s中出现的次数intc,d;inti=pos;intj=1;intcount=0;while(i=s.length){if(j==0||s.ch[i-1]==t.ch[j-1]){i++;j++;}elsej=Next(t,j);if(jt.length){c=IsNotCharactor(s.ch[i-1]);d=IsNotCharactor(s.ch[i-t.length-2]);if(c&&d)count++;j=1;}}returncount;}voidInitList_node(RowLinkList&L){L.head=(RowLink)malloc(sizeof(RowLink));//为L.head分配动态空间,并初始化L.tail=(RowLink)malloc(sizeof(RowLink));if(!L.head||!L.tail)exit(0);L.head-next=L.tail-next=NULL;L.len=0;}voidCreateNode_node(RowLink&rl,ShowDataElemelem){//创建节点rl=(RowLink)malloc(sizeof(RowLink));if(!rl)exit(0);rl-data.count=elem.count;rl-data.row=elem.row;rl-next=NULL;}voidadd_node(RowLinkList&ls,RowLinklink){//附加节点if(ls.head-next==NULL)ls.head-next=link;elsels.tail-next-next=link;ls.tail-next=link;ls.len++;}voidShowList(RowLinkListL){intn=0;RowLinkh=L.head-next;while(h){printf(%5d,h-data.row);printf(%d,h-data.count);printf(\n);//printf(%5d\n,h-data.location);n=n+h-data.count;h=h-next;}printf(\n);printf(一共出现的次数:%2d,n);printf(\n);}//串数据链表voidInitList(StringLinkList&L){L.head=(StringLink)malloc(sizeof(StringLink));L.tail=(StringLink)malloc(sizeof(StringLink));if(!L.head||!L.tail)exit(0);L.head-next=L.tail-next=NULL;L.len=0;}voidCreateNode(StringLink&sl,HStringstr){sl=(StringLink)malloc(sizeof(StringLink));if(!sl)exit(0);sl-str.ch=str.ch;sl-str.length=strlen(str.ch);InitList_node(sl-rowlist);sl-next=NULL;}voidaddnode(StringLinkList&ls,StringLinklink){if(ls.head-next==NULL)ls.head-next=link;elsels.tail-next-next=link;ls.tail-next=link;ls.len++;}voidfind(StringLinkList&stringLinkList,HStringhstrLine,introw){//在串数据链表stringLinkList,读出查找的串strkey,与传入的串hstrLine匹配//如果成功将匹配的次数与行数row,写入相对应的行行数据链表intcount;intlocation;StringLinkstringLink=stringLinkList.head-next;//找出第一个串while(stringLink){HStringstrkey=stringLink-str;count=Count_KMP(hstrLine,strkey,1);//求匹配的次数location=Index_KMP(hstrLine,strkey,1);if(location){printf(%s,strkey.ch);printf(在此行出现的位置为:);p