数据结构期末拯救计划:字符串

1.字符串和上学期在c语言学习的问题不大,主要算法思想有双指针,滑动窗口等,而这个部分的关键就在于记忆经典题目并会简单的c++vector操作

2.

【问题描述】如果字符串的一个子串(其长度大于1)的各个字符均相同,则称之为等值子串。试设计一算法,求出串S中一个长度最大的等值子串;如果串S 中不存在等值子串,则输出信息no

【输入形式】输入一个字符串,并以!结束

【输出形式】输出第一个出现的最长字符串,如果没有输出no

【样例输入】aabc123abc123cc!

【样例输出】aa

【样例输入】abceebccadddddaaadd!

【样例输出】ddddd

这道题目不需要使用滑动窗口,只需要直接计算,每次记录最长子串起始点的信息以及最长子串的长度即可

#include<iostream>
#include<string>
using namespace std;

void found(string s)
{
	int len = 0;
	int ret = 0;
	int start = 0;
	for (int i = 1; i < s.size(); i++)
	{
		if (s[i] == s[i - 1])
		{
			len++;
		}
		else
		{
			len = 1;
		}
		if (ret < len)
		{
			ret = len;
			start = i - ret + 1;
		}
	}
	if (ret > 1)
	{
		for (int j = 0; j < ret; j++)
		{
			cout << s[start + j];
		}
	}
	else
	{
		printf("no");
	}
}
int main()
{
	string a;
	int i = 0;
	while (1)
	{
		char d;
		cin >> d;
		if (d == '!')
		{
			break;
		}
		else
		{
			a.push_back(d);
		}
	}
	found(a);
	return 0;
}

3.

【问题描述】判断两个字符串是否匹配,其中一个字符串中包括通配符*或?(串)。*代表0个或多个字符,?代表一个字符
【输入形式】分两行入两个字符串,以#结束,其中一个字符串中包括通配符*或?(串),另一个为不包含*和?的确定字符串
【输出形式】判断两个字符串是否匹配,若匹配,输出yes,不匹配输出no
【样例输入】

 da?a*tu*e#
 datastructure#
【样例输出】
 yes
【样例说明】 第一个字符串中包含通配符,第二个字符串为确定字符串。字符串中可能有空格,字母均为小写字母。
【评分标准】 请尽量使用效率高的算法,如结合KMP算法的思想。 

提示:?可看做对任一字符的匹配,*可看做对给出的有效字符(串)的匹配。

首先这道题可以使用递归的思想,递归出口为s1遍历完成,如果s2也遍历完成,则返回true,,没有则返回false,然后执行操作,如果字母为*,则有两种情况,一种是空字符,则直接在s1字符串把这个字符跳过,如果代表多个字母的情况,则s2字符串往后一位进行递归,如果是?,则s1,s2同时跳过一位,如果是普通字符,则进行正常比较

#include<iostream>
#include<string>
using namespace std;

bool match(string s1, int start1, string s2, int start2)
{
	if (start1 == s1.size() && start2 == s2.size())
	{
		return true;
	}
	if (start1 == s1.size() && start2 != s2.size())
	{
		return false;
	}
	char p = s1[start1];
	if (p == '*')
	{
		return match(s1, start1 + 1, s2, start2) || (start2 < s2.size()) && (s1, start1, s2, start2 + 1);
	}
	else if(p=='?')
	{
		return match(s1, start1 + 1, s2, start2 + 1);
	}
	else
	{
		return start2 < s2.size() && p == s2[start2] && match(s1, start1 + 1, s2, start2 + 1);
	}
}
int main()
{
	string s1;
	string s2;
	cin >> s1;
	cin >> s2;
	if (match(s1, 0, s2, 0))
	{
		cout << 'Yes';
	}
	else
	{
		cout << 'No';
	}
	return 0;
}

3.

【问题描述】给定一个字符串s,找出s里第一次出现的最长的回文子串。

【样例输入1】babad
【样例输出1】bab

【样例输入2】cbbd
【样例输出2】bb

回文子串就是典型的双指针算法,左右指针同时向中间移动,如果出现不同则不是,但是这里介绍一种新颖的算法,用于寻找回文子串

本题思路:本题采用一种简单的方法寻找子串,即从中间一点或两点(字符串长度为奇数为一点,偶数为两点,为了节省讨论直接全部试一遍),一个向左一个向右移动,直到越界或者不构成回文条件为止,注意截取时由于left越界需要加1,为什么截取长度为right-left-1,由于此时left为左边界的左侧元素,right为有边界的右侧元素,按照传统的长度计算right-left+1,而此时right和left的越界导致长度增加了2,所以right-left+1-2=right-left-1

#include<iostream>
#include<string>
using namespace std;
string find(string& s, int left, int right)
{
	while (left >= 0 && right < s.size() && s[left] == s[right])
	{
		left--;
		right++;
	}
	return s.substr(left + 1, right - left-1);
}
string findmax(string s)
{
	if (s.empty())
	{
		return "";
	}
	string ret = "";
	for (int i = 0; i < s.size(); i++)
	{
		string s1 = find(s, i, i);
		string s2 = find(s, i, i + 1);
		if (s1.size() > ret.size())
		{
			ret = s1;
		}
		if (s2.size() > ret.size())
		{
			ret = s2;
		}
	}
	return ret;
}
int main()
{
	string s;
	cin >> s;
	cout<<findmax(s);
	return 0;
}

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值