【C】KMP算法

问题 A: 动物简介(animal)

时间限制: 1 Sec  
内存限制: 64 MB

提交: 30  
解决: 16

[
提交][
状态][
TK题库][命题人:
]

题目描述

到了动物园,琦琦开心得跳起来。哗,这里好多动物呀,有老虎,有狮子……,在开心之余,琦琦也不忘妈妈的教导:观察动物时要认真仔细,还要看动物园附上的动物简介呀。
动物的简介原来还有英文版的呢!为了卖弄自己的英文水平,琦琦就告诉妈妈每张动物简介里出现了多少次该动物的名称。注意:琦琦只认识小写字母,而且她只认得动物的单词,因此她认为monkeys或者smonkey或者smonkeys都是出现了monkey这个词。
你能编程完成琦琦的任务吗?

输入

 输入文件共n+2行:
第1行为数字n(n<=3000),表示该动物的简介共有n行。
第2行为一个单词,表示琦琦认识的动物名称。
接着是n行,每行为一个长度小于250个字符的字符串,表示动物的简介。

输出

 输出文件共1行,为简介里出现了多少次琦琦能识别出的动物的单词。

样例输入

2
snake
The snake is a long and thin animal.
Snakes have no legs or feet.

样例输出

1

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<string>
using namespace std;
int nextval[300];
void getnextval(string s){
	int j=-1;
	nextval[0]=-1;
	for(int i=0;i<s.size();i++){
		while(j!=-1&&s[i]!=s[j+1]){
			j=nextval[j];
		}
		if(s[i]==s[j+1]) j++;
		if(j==-1||s[i+1]!=s[j+1]) nextval[i]=j;
		else nextval[i]=nextval[j];
	}
}
int KMP(string text,string pattern){
	int n=text.size(),m=pattern.size();
	getnextval(pattern);
	int ans=0,j=-1;
	for(int i=0;i<n;i++){
		while(j!=-1&&text[i]!=pattern[j+1]){
			j=nextval[j];
		}
		if(text[i]==pattern[j+1]) j++;
		if(j==m-1){
			ans++;
			j=nextval[j];
		}
	}
	return ans;
}
int main(){
	string pattern;
	int n,i;
	int num=0;
	cin>>n;
	getchar();
	getline(cin,pattern);
	for(i=0;i<n;i++){
		string text;
		getline(cin,text);
		num+=KMP(text,pattern);
	}
	cout<<num<<endl;
	return 0;
}

问题 B: P2 统计单词数

时间限制: 1 Sec  
内存限制: 128 MB

提交: 33  
解决: 8

[
提交][
状态][
TK题库][命题人:
]

题目描述

统计单词数 (stat.cpp/c/pas)
一般的文本编辑器都有查找单词的功能,该功能可以快速定位特定单词在文章中的位置,有的还能统计出特定单词在文章中的次数。

现在,请你编程实现这一功能,具体要求是:给定一个单词,请你输出它在给定的文章中出现的次数和第一次出现的位置。注意:匹配单词时,不区分大小写,但要求完全匹配,即单词必须与文章中某一独立残次在不区分大小写的情况下完全相同(参见样例1),如果给定单词仅是文章中某一单词的一部分则不算匹配(参见样例2)。

输入

输入文件共2行。

第1行为一个字符串,其中只包含字母,表示给定单词;

第2行为一个字符串,其中只可能包含字母和空格,表示给定的文章。

输出

只有1行,如果在文章中找到给定单词则输出两个整数,两个整数之间用一个空格隔开,分别是单词在文章中出现的次数和第一次出现的位置(即在文章中第一次出现时,单词首字母在文章中的位置,位置从0开始);如果单词在文章中没有出现,则直接输出一个整数-1。

样例输入

输入样例1:
To
to be or not to be is a question
输入样例2:
to
Did the Ottoman Empire lose its power at that time

样例输出

输出样例1:
2 0
输出样例2:
-1

提示

1<=单词长度<=10。

1<=文章长度<=10,000,000。

#include<stdio.h>
#include<iostream>
#include<string>
#include<sstream>
using namespace std;
int nextval[15];
void zhuanhuan(string &str){
	int len=str.size();
	int i;
	for(i=0;i<len;i++){
		if(str[i]>='A'&&str[i]<='Z') str[i]=str[i]-'A'+'a';
	}
}//全部大写转小写
void getnextval(string pattern){
	int len=pattern.size();
	int j=-1;
	nextval[0]=-1;
	for(int i=0;i<len;i++){
		while(j!=-1&&pattern[i]!=pattern[j+1]){
			j=nextval[j];
		}
		if(pattern[i]==pattern[j+1]) j++;
		if(j==-1||pattern[i+1]!=pattern[j+1]){
			nextval[i]=j;
		}
		else nextval[i]=nextval[j];
	}
}
int KMP(string pattern,string text,int &first){
	int len1=pattern.size(),len2=text.size();
	getnextval(pattern);
	int ans=0,j=-1;
	for(int i=0;i<len2;i++){
		while(j!=-1&&text[i]!=pattern[j+1]){
			j=nextval[j];
		}
		if(text[i]==pattern[j+1]) j++;
		if(j==len1-1&&text[i+1]==' '&&(i-len1<0||text[i-len1]==' ')){//因为规定是一个单词,而不能是某个单词的一部分 
			ans++;
			j=nextval[j];
			if(ans==1) first=i-len1+1;
		}
	}
	return ans;
}
int main(){
	string pattern,text;
	getline(cin,pattern);
	getline(cin,text);
	zhuanhuan(pattern);
	zhuanhuan(text);
	getnextval(pattern);
	int first=0;
	int num=KMP(pattern,text,first);
	if(num==0) cout<<"-1"<<endl;
	else cout<<num<<" "<<first<<endl;
	return 0;
}
 

问题 C: 剪花布条

时间限制: 1000 Sec  
内存限制: 10000 MB

提交: 18  
解决: 8

[
提交][
状态][
TK题库][命题人:
]

题目描述

一块花布条,里面有些图案,另有一块直接可用的小饰条,里面也有一些图案。对于给定的花布条和小饰条,计算一下能从花布条中尽可能剪出几块小饰条来呢?

输入

输入中含有一些数据,分别是成对出现的花布条和小饰条,其布条都是用可见ASCII字符表示的,可见的ASCII字符有多少个,布条的花纹也有多少种花样。花纹条和小饰条不会超过1000个字符长。如果遇见#字符,则不再进行工作。

输出

输出能从花纹布中剪出的最多小饰条个数,如果一块都没有,那就老老实实输出0,每个结果之间应换行。

样例输入

abcde a3
aaaaaa  aa
#

样例输出

0
3

#include<stdio.h>
#include<iostream>
#include<string>
#include<string.h>
using namespace std;
int nextval[1010];
void getnextval(string pattern){
	memset(nextval,0,sizeof(nextval));
	int len=pattern.size();
	int j=-1;
	nextval[0]=-1;
	for(int i=0;i<len;i++){
		while(j!=-1&&pattern[i]!=pattern[j+1]){
			j=nextval[j];
		}
		if(pattern[i]==pattern[j+1]) j++;
		if(j==-1||pattern[i+1]!=pattern[j+1]) nextval[i]=j;
		else nextval[i]=nextval[j];
	}
}
int KMP(string pattern,string text){
	int len1=pattern.size(),len2=text.size();
	getnextval(pattern);
	int ans=0,j=-1;
	for(int i=0;i<len2;i++){
		while(j!=-1&&text[i]!=pattern[j+1]){
			j=nextval[j];
		}
		if(text[i]==pattern[j+1]) j++;
		if(j==len1-1){
			ans++;
			j=-1;
		}
	}
	return ans;
}
int main(){
	string pattern,text;
	cin>>text;
	while(text!="#"){
		cin>>pattern;
		getnextval(pattern);
		int num=KMP(pattern,text);
		cout<<num<<endl;
		cin>>text;
	}
	return 0;
}

    原文作者:KMP算法
    原文地址: https://blog.csdn.net/Li_Jiaqian/article/details/79485335
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞