NOI1.7.26 字符串最大跨距 题解(C++)

NOI1.7.26 字符串最大跨距 题解(C++)

在这里插入图片描述

这道题可以说是字符数组中考察点较多的题目之一了,不说太多了,请看大屏幕 听题:

26:字符串最大跨距

总时间限制: 1000ms 内存限制: 65536kB
描述

有三个字符串S,S1,S2,其中,S长度不超过300,S1和S2的长度不超过10。想检测S1和S2是否同时在S中出现,且S1位于S2的左边,并在S中互不交叉(即,S1的右边界点在S2的左边界点的左侧)。计算满足上述条件的最大跨距(即,最大间隔距离:最右边的S2的起始点与最左边的S1的终止点之间的字符数目)。如果没有满足条件的S1,S2存在,则输出-1

输入

三个串:S1, S2, S3,其间以逗号间隔(注意,S1, S2, S3中均不含逗号和空格真香 );

输出

S1和S2在S最大跨距;若在S中没有满足条件的S1和S2,则输出-1。

样例输入
abcd123ab888efghij45ef67kl,ab,ef

样例输出
18

乍一看这输入就知道此题的出题人没想让你轻松过题了,像作者连个getline()都不知道,还是乖乖自己写出input函数输入吧。还有注意一下:s2后面可没有逗号哦
input函数代码如下:

char input(char s[]){
	int n = 0;//这里充当一下数组s的下标
	while(1){
		char k = getchar();//获取一个字符
		if(k == ','){//华丽的预判
			break;
		}else{
			s[n] = k;
			n++;
		}
	}
}

其实,这题并没有说s1,s2,s3不为空,所以还是踏踏实实做人 写出预判代码:

if(lena == 0||lenb == 0||len == 0){//s1,s2,s3都不为空
	cout<<"-1";
	return 0;
}

记住:

在这里插入图片描述

还有一个比较毒瘤的东西就是题目中用标记的一句话:且S1位于S2的左边,并在S中互不交叉,如果你没有写有关这个的话,请你试试如下测试数据:abcde,abcd,bcd。你就会知道为什么了,呵呵~

现在说一下本题的重头戏:求出最长跨度,因为是最长,所以s2要找最后一次出现的地方。在样例输入中的跨度是18,就是下面这个字符串的长度:cd123ab888efghij45,不信的话可以自己数数(反正作者已经数过了…)
下面有两种可出结果的方法:
1.s2的结尾(不是s2的最后一个,是s2的后一个)-s1的结尾-s1长度
2.s2的开头-s1的结尾
作者为了**(你们知道),选第一种方法,第二种可以自己试试,不会太难。
是时候放出完整代码了 :

#include<bits/stdc++.h>
using namespace std;

char input(char s[]){
	int n = 0;//这里充当一下数组s的下标
	while(1){
		char k = getchar();//获取一个字符
		if(k == ','){//华丽的预判
			break;
		}else{
			s[n] = k;
			n++;
		}
	}
}
bool found(char s[],char f[],int len,int begin){
	int p = 0;
	for(int j = begin;j<begin+len;j++){//遍历一遍
		if(s[j] != f[p]){//不一样
			return false;//直接解决
		}else{
			p++;//下标移动
		}
	}
	return true;
}
int main(){
	char s[305] = {0};
	char a[15] = {0};
	char b[15] = {0};
	
	//初始化一下不会怎么样
	input(s);
	input(a);
	cin>>b;//不能再用input了
	
	int len = strlen(s);
	int lena = strlen(a);
	int lenb = strlen(b);//不说了
	
	//预判
	bool k = true/*以i为起点的S能否找到s1,s2*/,
	turn = false/*当前s中s1,s2找到过吗*/;
	int begin/*s1结束*/,end/*s2开始*/,p = 0/*下标*/;
	
	for(int i = 0;i<len;i++){
		k = found(s,a,lena,i);//以i为起点能不能找到
		if(k){
			begin = i+lena;
			turn = true;//找到过
			break;
		}
	}
	if(!turn){//没找到s1
		cout<<"-1";
		return 0;
	}
	turn = false;
	p = 0;
	//重复利用一下
	for(int i = 0;i<len;i++){
		k = found(s,b,lenb,i);//以i为起点能不能找到
		if(k){
			end = i;
			turn = true;//找到过
		}
	}
	if(!turn){//没找到s2
		cout<<"-1";
		return 0;
	}
	if(end-begin<0){//如果是负数,那么就是说交叉了
		cout<<"-1";
		return 0;
	}else{
		cout<<end-begin;
	}
	return 0;
}

本题的讲解到此结束。有兴趣听个笑话的就继续往下翻:

老师向同学们讲解完<<掩耳盗铃>>这篇文章后…
老师:小明(又是他 ),说说类似《掩耳盗铃》的情况还有哪些?
老师希望的的回答:像自欺欺人这样的行为之类的… …
小明是个思路清奇的学生,于是… …
小明:像下课铃响了,老师们装作没听见,继续上课。
老师:。。。。。。
班长跑到班主任那里说:班主任,小明又把老师气晕了!!!
班主任无奈地叹了口气:这是第376回了。。。

发布了20 篇原创文章 · 获赞 1 · 访问量 464

猜你喜欢

转载自blog.csdn.net/jerry20183/article/details/104381516
今日推荐