【字符串相关】洛谷刷题计划

T1:P3741 :honoka的键盘

今天做的第一道题是输入长度为n的字符串(仅由V、K两种字符组成),判断组合‘VK’的数量,其中,有一次修改字符的机会,使得产生最多的VK个数(如VV,修改第二个V可变成VK,使VK数量增加一个)。

本题的思路就是,遍历两次字符串。首先,就是简单的把里面符合的VK组合找到,然后记录数量,记住,找到后要将其修改成别的字符,就把他们变成小写的v和k吧。
接着,第二次遍历字符串。寻找可以修改一下符合要求的。
不难看出,V和K只有4种组合,VV,KK,VK,KV,其中,若只能修改一个字符,KV肯定是不符合条件的。而VK在前一步已经全部找出并记录了,所以本步骤就是用来寻找VV和KK字符。但是注意!只有一次修改的机会哦,所以我们发现一个VV或KK就可以给计数加一,然后停止了。
一些细节:

  1. 关于字符串的定义与读入(数组版):
char s[103];//题目规定字符个数小于100
gets(s);//scanf("%s",s)

string版:

string s;
cin>>s;//遇见空格就停,和scanf同理
getline(cin,s);//类比gets()

用scanf/cin会跳过前面的空白字符字符,后来遇到空白字符会停止。
为了一次读入一整行输入,可以使用gets函数,它是遇到换行符才停止,并且不会把这个换行符存入字符串数组中

example:

char sentence[SENTEN_LEN+1];
scanf("%s",sentence);
//键入:To C or not to C:that is the question.
printf("%s",sentence);
//输出结果:To
//如果下面还有scanf("%s",s);,将会从To后面的空格开始,读入C,遇到C后的空格停止,以此类推。
gets(sentence);
printf("%s",sentence);// 

也可以直接用string定义一个字符串变量。
然后利用cin函数直接键入,好处就是不用考虑那么多了,就像输入数字一样。

  1. 字符串操作函数(头文件:#include<string.h>)
    ·strlen(s):计算字符串的长度,不算最后的空白字符

      char s[4] = "abc';//s[0]=a,s[1]=b,s[2]=c,s[3] = '\0'
      printf("%d",strlen(s));
      //结果:3
    

具体代码如下:

#include<iostream>
#include<string.h>
using namespace std;
int main()
{
  string s;
  //char s[103]; 
  int flag = 1;//标志是否修改过字符 
  int n,cnt = 0;
  cin>>n>>s;
  //gets(s);
  for(int i=0;i<n-1;i++)//string:s.length()  char []:strlen(s),都是不计入最后一个空白字符'\0'的
  {
  	if(s[i]=='V'&&s[i+1]=='K')
  	{
  		cnt++;
  		s[i] = 'v';
  		s[i+1] = 'k';
  	}
  }
  for(int i=0;i<n-1;i++)//注意是小于n-1,因下面i+1,不要越界 
  {
  	if(s[i]==s[i+1])
  	{ 
  		cnt++;
  		break;
  	} 
  }
  cout<<cnt;
  return 0;

}

T2: P5015标题统计

题目描述
凯凯刚写了一篇美妙的作文,请问这篇作文的标题中有多少个字符? 注意:标题中可能包含大、小写英文字母、数字字符、空格和换行符。统计标题字 符数时,空格和换行符不计算在内。
在这里插入图片描述
题目思路
本题主要考察了对处理字符串函数的应用。因为题目规定了
对于 100%100% 的数据,1 ≤ |s| ≤ 51≤∣s∣≤5,输入可能包含大、小写英文字母、数字字符、空格和行末换行符。
所以定义一个字符数组即可,然后利用刚才提到的gets()读入(可以读入空白符),循环长度根据strlen()得到。
然后再遍历一遍找出非空白字符的个数即可。
代码如下:

#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
int main()
{
	char s[6];
	int cnt=0;
	gets(s);
	for(int i=0;i<strlen(s);i++)
	{
		if(s[i]!=' ')
			cnt++;
	}
	cout<<cnt;
	return 0;
	
}

T3:P1308 [NOIP2011 普及组] 统计单词数

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

样例1

输入

To
to be or not to be is a question

输出

2 0

样例2

输入

to
Did the Ottoman Empire lose its power at that time

输出

-1

分析:一开始理解错了题意,没有注意到“完全匹配”这个要求,把所有符合要求的都统计了出来,后来错了很多测试点,然后在此基础上,就加了几个判断条件:
1.将输入的字符串都转换为大写(大小写统一即可)
2.若第一个字母就不匹配,直接找到下一个“单词”(即两个空格中间的字母组合)while(src[i]!=' '||src[i+1]!='\0') i++;
3.”子串“最后一个单词都与长串匹配成功后,看此时长串的下一个单词是不是空格末尾,若是,则说明这一次匹配成功。否则匹配失败,步骤同2.
但是!!有一个测试点一直没过。。。。。也不知道错哪里了,本身我的代码写的可能就比较混乱吧,不过相比昨天有了一点进步,先干点别的,明天再看看~~
”垃圾代码如下:“

#include<iostream>
#include<string.h>
using namespace std;
int main()
{
	string tar,src;
	int pos=-1,cnt=0,flag;
	
	getline(cin,tar);
	getline(cin,src);
	int lent = tar.length(),
		lens = src.length();
	for(int i=0;i<lent;i++)
        tar[i]=toupper(tar[i]);  //转成大写 
    for(int i=0;i<lens;i++)
     	src[i]=toupper(src[i]);
	//cout<<endl<<tar<<" "<<src;
	//用暴力的方法做,KMP还不会。 
	for(int i=0;i<=lens-lent;i++)
	{
		flag=1; 
		if(src[i]!=tar[0])//某个单词的第一个字母就不匹配,跳到下一个单词 
		{
			flag = 0;
			while(src[i]!=' '&&i<lens)//跳到下一个字符 
     			i++;
		}
			
		//if(src[i]==tar[0])//每次都是匹配第一个字符,若不相等,找到下一个单词的开头 
		else
		{ 
			for(int j=0;j<lent&&flag;j++)//从tar的第二字符开始判断,中间有不匹配则flag=0,退出这个单词的匹配。 
			{
				if(i<lens&&(src[i]==tar[j]))//保证不越界的同时,看看tar从头到尾是否都能匹配上src。 
				{
					i++;//src的字符下标自动加一。 
					if(j == lent-1)//匹配到了最后一个字符 
					{
						if(src[i]==' '||src[i]=='\0')//看长句子中的匹配情况,是不是一个单词(后面跟着空格或结束) 
							flag = 1;//什么也不做 
						else
							flag = 0;//不是完全匹配 
					}
				}
     			else
     			{
     				flag = 0;//这一次没匹配成功。
     				while(src[i]!=' '&&i<=lens-lent)//跳到下一个字符 
     					i++;
				 }		 
			}
			if(flag)//匹配成功
			{
				if(cnt==0)
					pos = i-lent;//标记第一个 
				cnt++; 
			}
		}
	}
	if(cnt>0)
		cout<<cnt<<" "<<pos;
	else
		cout<<pos;
	
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值