【基础练习】【字符串处理】noip2011普及组第2题 统计单词数题解

这又是一道成功加入“容易吗”系列的基础题= =原本很简单,可是我一开始太大意看错了题,以为是让输出该单词是第几个单词,实际上应该输出该单词的首字母在第几个位置;改过后只得了二十分,看了一组数据,原来第一个单词前面可以有前导空格——幸亏其他单词前没有,否则还真不知道怎么办;实现的时候又出了各种问题。于是我决定总结一下。

题目:

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

输入格式:

  输入文件名为stat.in ,2 行。

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

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

输出格式:

  输出文件名为stat.out 。

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

1≤ 单词长度≤10。

1≤ 文章长度≤1,000,000。

二话不说,先上代码

//tongjidancigeshu
#include<iostream>
#include<string>
#include<cctype>//for tolower
#include<cstdio>
using namespace std;

inline string change(string s){//wxjlzbcd神犇表示,加inline后变成内联函数,内联到宏中,可以稍微加速,暴搜可用,但是我不大了解,慢慢学习
	for (int i=0;i<s.length();i++) s[i]=tolower(s[i]);
	return s;//don't forget//刚开始竟然忘了return s,导致出现错误好像是访问无效内存rewritten
} 

int main(){
	freopen("1.txt","r",stdin);//freopen输入输出,粘代码党记得删除O(∩_∩)O~再次强化要用cstdio头文件
	freopen("2.txt","w",stdout);
	string point,s,words;//point记录要查找的单词,s是文章整体读入,words是截取的文章中的单个单词
	getline(cin,point);//注意:point一定要用getline读入!否则下一个getline(cin,s)会直接读取point后的回车,导致s=''!
	point=change(point);//tolower only use for single char tolower位于cctype头文件中,只用于单个字符
	getline(cin,s);//if the third position is empty it's \n= =关于这一点,正文中会介绍↓
	s=change(s);
	int i,pos=0,anspos=-1,ans=0;//anspos要设为-1,如果设为0,由于初始位置也是0,初始位置就是第一个单词的话会出现判断错误
	for (i=0;i<s.length();i++){
		if (s[i]==' '){//每次找到空格,截取空格前面的单词比较
			words=s.substr(pos,i-pos);//notice the usage!注意s.substr的用法,稍后介绍↓
			if (point==words){
				if (anspos==-1) anspos=pos;//免去布尔变量的使用
				ans++;
			}
			pos=i+1;
		}
	}
	if (anspos==-1) cout<<anspos<<endl;
	else cout<<ans<<' '<<anspos<<endl;
	return 0;
}

为防止大家看不懂我不标准的英文注释,代码注释采用中英双语= =

关于代码中提到的两点:

1.getline()

关于这一点,这里有一份相当好的资料,来自新浪博主sundowner,他在博客园也有博客

原文地址:http://blog.sina.com.cn/s/blog_60263c1c0101ck25.html

作者博客园博客:http://www.cnblogs.com/overcode

作者所言如下:

学习C++的同学可能都会遇到一个getline()函数,譬如在C++premer中,标准string类型第二小节就是“用getline读取整行文本”。书上给的程序如下:

int main()

{

    string line:

    while(getline(cin,line))

    cout<<line<<endl;

    return 0;

}

大家会发现运行时怎么也跳不出循环,甚至会发生各种莫名其妙的错误。这是为什么呢?在这里我给大家做一个详细的讲解。

首先给大家介绍一下getline()函数(个人觉得百度百科给的果断不够详细)

大家百度会发现getline()的原型是istream& getline ( istream &is , string &str , char delim );

其中 istream &is 表示一个输入流,譬如cin;string&str表示把从输入流读入的字符串存放在这个字符串中(可以自己随便命名,str什么的都可以);char delim表示遇到这个字符停止读入,在不设置的情况下系统默认该字符为‘\n‘,也就是回车换行符(遇到回车停止读入)。给大家举个例子:

string line;

cout<<"please cin a line:"

getline(cin,line,‘#‘);

cout<<endl<<"The line you give is:"line;

那么当我输入"You are the #best!" 的时候,输入流实际上只读入了"You are the ",#后面的并没有存放到line中(应该是在缓冲区里吧)。然后程序运行结果应该是这样的:

 please cin a line:You are the #best!

 The line you give is:You are the 

而且这里把终止符设为#,你输入的时候就算输入几个回车换行也没关系,输入流照样会读入,譬如:

                              please cin a line:You are the best!

//这里输入了一个回车换行

      Thank you!

      #   //终止读入

      The line you give is:You are the best!

//换行照样读入并且输出

        Thank you!

以上就是getline()函数一个小小的实例了。

那么如果把getline()作为while的判断语句会怎么样呢?

让我们一起来分析一下while(getline(cin,line))语句

注意这里默认回车符停止读入,按Ctrl+Z或键入EOF回车即可退出循环。

在这个语句中,首先getline从标准输入设备上读入字符,然后返回给输入流cin,注意了,是cin,所以while判断语句的真实判断对象是cin,也就是判断当前是否存在有效的输入流。在这种情况下,我想只要你的电脑不中毒不发神经你的输入流怎么会没有效?所以这种情况下不管你怎么输入都跳不出循环,因为你的输入流有效,跳不出循环。

然而有些同学误以为while判断语句的判断对象是line(也就是line是否为空),然后想通过直接回车(即输入一个空的line)跳出循环,却发现怎么也跳不出循环。这是因为你的回车只会终止getline()函数的读入操作。getline()函数终止后又进行while()判断(即判断输入流是否有效,你的输入流当然有效,满足条件),所以又运行getline()函数,所以,你懂了吧。。。

也就是说,实际上函数为getline(流的名称,字符串名称,结束符)。鄙人第一次输入的时候忘了cin,后果相当严重啊···

再次感谢上文作者sundowner,我才知道sundowner意思是:流浪汉;无业游民;傍晚喝的饮料···

2.s.substr()

这个函数用于复制字符串的一段子串。

这个函数是针对STL的string类型的,c字符串是不可以用的!

这个函数str在后面,c字符串函数str基本都是在前面!

这个函数使用时前面一定要加字符串名,因为这是STL!

这个函数使用格式为:s.substr(起始位置(int),截取长度(int)),鄙人刚开始竟然用了s.begin()+pos···

更悲剧的是,鄙人看百科竟然看成了PHP中的substr TUT

只输入一个数字时,为起始位置,默认截取到字符串尾。

起始位置不可以是负数,否则···

codevs上大神的代码鄙人根本看不懂,但至少学习了一个函数s.erase 这个似乎是eraser来源的单词的意思是:清除,擦除

如果有谁有更好的方法,请务必与我交流,鄙人不胜感激。

——————————————————————

马年最后一天泡机房,今天上午来的时候想的是:听一下群的基础,只写作业不刷题。

但我看到洛谷排名鄙人终于进了前200且超过千反田妹妹后,不胜欣喜,于是忍不住刷了一道水题。

哪知这水题···好吧AC掉之后一看表十点五十···写完题解一看表十一点四十···

我马年最后一次机房的一上午,就这么栽倒在一道水题上

TUT OTZ _(:з」∠)_
我已不知如何形容我此时澎湃的心潮(/?Д?)/((???|||))

——举头西北浮云,倚天万里须长剑。

时间: 2024-08-06 17:53:43

【基础练习】【字符串处理】noip2011普及组第2题 统计单词数题解的相关文章

NOIP2011 普及组 T3 洛谷P1309 瑞士轮

今天题做太少,放道小题凑数233 题目背景 在双人对决的竞技性比赛,如乒乓球.羽毛球.国际象棋中,最常见的赛制是淘汰赛和循环赛.前者的特点是比赛场数少,每场都紧张刺激,但偶然性较高.后者的特点是较为公平,偶然性较低,但比赛过程往往十分冗长. 本题中介绍的瑞士轮赛制,因最早使用于1895年在瑞士举办的国际象棋比赛而得名.它可以看作是淘汰赛与循环赛的折衷,既保证了比赛的稳定性,又能使赛程不至于过长. 题目描述 2*N 名编号为 1~2N 的选手共进行R 轮比赛.每轮比赛开始前,以及所有比赛结束后,都

NOIP2011-普及组复赛-第二题-统计单词数

题目描述 Description 一般的文本编辑器都有查找单词的功能,该功能可以快速定位特定单词在文章中的位置,有的还能统计出特定单词在文章中出现的次数.  现在,请你编程实现这一功能,具体要求是:给定一个单词,请你输出它在给定的文章中出现的次数和第一次出现的位置.注意:匹配单词时,不区分大小写,但要求完全匹配,即给定单词必须与文章 中的某一独立单词在不区分大小写的情况下完全相同(参见样例1 ),如果给定单词仅是文章中某一单词的一部分则不算匹配(参见样例2 ). 输入输出格式 Input/out

洛谷-统计单词数-简单字符串

题目描述 Description 一般的文本编辑器都有查找单词的功能,该功能可以快速定位特定单词在文章中的位置,有的还能统计出特定单词在文章中出现的次数.  现在,请你编程实现这一功能,具体要求是:给定一个单词,请你输出它在给定的文章中出现的次数和第一次出现的位置.注意:匹配单词时,不区分大小写,但要求完全匹配,即给定单词必须与文章 中的某一独立单词在不区分大小写的情况下完全相同(参见样例1 ),如果给定单词仅是文章中某一单词的一部分则不算匹配(参见样例2 ). 输入输出格式 Input/out

洛谷 P1308 统计单词数【字符串+模拟】

P1308 统计单词数 题目描述 一般的文本编辑器都有查找单词的功能,该功能可以快速定位特定单词在文章中的位置,有的还能统计出特定单词在文章中出现的次数. 现在,请你编程实现这一功能,具体要求是:给定一个单词,请你输出它在给定的文章中出现的次数和第一次出现的位置.注意:匹配单词时,不区分大小写,但要求完全匹配,即给定单词必须与文章 中的某一独立单词在不区分大小写的情况下完全相同(参见样例1 ),如果给定单词仅是文章中某一单词的一部分则不算匹配(参见样例2 ). 输入输出格式 输入格式: 输入文件

noip2011普及组——统计单词数

统计单词数 时间限制:1 s 内存限制:128MB [问题描述]一般的文本编辑器都有查找单词的功能,该功能可以快速定位特定单词在文章中的位置,有的还能统计出特定单词在文章中出现的次数.现在,请你编程实现这一功能,具体要求是:给定一个单词,请你输出它在给定的文章中出现的次数和第一次出现的位置.注意:匹配单词时,不区分大小写,但要求完全匹配,即给定单词必须与文章中的某一独立单词在不区分大小写的情况下完全相同(参见样例1),如果给定单词仅是文章中某一单词的一部分则不算匹配(参见样例2). [输入]输入

守望者的逃离(2007年普及组第3题)| 贪心算法

守望者的逃离(2007年普及组第3题) [问题描述] 恶魔猎手尤迪安野心勃勃,他背叛了暗夜精灵,率深藏在海底的那加企图叛变,守望者在与尤迪安的交锋中遭遇了围杀.被困在一个荒芜的大岛上.为了杀死守望者,尤迪安开始对这个荒岛施咒,这座岛很快就会沉下去,到那时岛上的所有人都会遇难:守望者的跑步速度为17m/s, 以这样的速度是无法逃离荒岛的.庆幸的是守望者拥有闪烁法术,可在1s内移动60m,不过每次使用闪烁法术都会消耗魔法值10点.守望者的魔法值恢复的速度为4点/s,只有处在原地休息状态时才能恢复.

JSK-27321 统计单词数【字符串】

统计单词数 一般的文本编辑器都有查找单词的功能,该功能可以快速定位特定单词在文章中的位置,有的还能统计出特定单词在文章中出现的次数. 现在,请你编程实现这一功能,具体要求是:给定一个单词,请你输出它在给定的文章中出现的次数和第一次出现的位置. 注意:匹配单词时,不区分大小写,但要求完全匹配, 即给定单词必须与文章中的某一独立单词在不区分大小写的情况下完全相同(参见样例 1), 如果给定单词仅是文章中某一单词的一部分则不算匹配(参见样例 2). 输入格式 第 1 行为一个字符串,其中只含字母,表示

【基础练习】【卡特兰数】栈 2003年NOIP全国联赛普及组第三题 题解

卡特兰数,这是一向掌握不大熟练的内容,今天借NOIP2003普及组的第三题来总结一下.当然由于原题数据弱抱,不需要高精.如果有时间我会不断补充这篇文章里的内容. 二话不说上代码 //Catalan #include<iostream> using namespace std; long long n,f[20]={0}; /*NO.1 f[n+1]=f[i]*f[n-i]from 0 to n plus f[0]=1 int main(){ cin>>n; f[0]=1;f[1]=

NOIP2011普及组 表达式的值

题面 https://vijos.org/p/1808 看了lrj124同学的题解,使用stack来写. 题解 https://vijos.org/p/1808/solution 注意函数内部改变一个变量可能会改变另一个变量...变量会相互计算... 比如 a.zero = (a.zero*(b.zero+b.one)+a.one*b.zero)%mod; a.one = a.one*b.one%mod; 如果先赋a.one,a.zero就不对了 计算的顺序很重要