题目
给你一个字符串数组(每个字符串均由小写字母组成)和一个字符规律(由小写字母和 . 和 * 组成),识别数组中哪些字符串可以匹配到字符规律上。
‘.’匹配任意单个字符,‘*’匹配零个或多个前面的那一个元素,所谓匹配,是要涵盖整个字符串的,而不是部分字符串。
输入描述
第一行为空格分隔的多个字符串,单个字符串长度从1到100,字符串个数从1到100
第二行为字符规律,1<=字符规律长度<=50
不需要考虑异常场景
输出描述:
匹配的字符串在数组中的下标(从0开始),多个匹配时下标升序并用英文逗号分隔,若均不匹配输出-1.
示例1
输入
ab aab
.*
输出
0,1
说明
ab中a匹配. b匹配* 可以完全匹配;aab中a匹配. ab匹配* 可以完全匹配;输出对应字符串数组下标0,1
示例2
输入
ab aab
a.b
输出
1
说明
aab中第一个a匹配a,第二个a匹配. b匹配b可以全匹配;输出对应的字符串数组下标1
首先,我们定义一个二维数组dp
,其中dp[i][j]
表示字符串s
的前i
个字符和模式p
的前j
个字符是否匹配。注意这里i
和j
是从0开始的索引。
解题思路
动态规划的状态转移方程如下:
- 当
p[j-1]
是普通字符或.
时:
- 如果
s[i-1]
和p[j-1]
相等,或者p[j-1]
是.
(可以匹配任意字符),则dp[i][j] = dp[i-1][j-1]
。 - 否则,
dp[i][j] = False
。
- 当
p[j-1]
是*
时:
- 如果
s[i-1]
和p[j-2]
相等,或者p[j-2]
是.
,那么dp[i][j]
可以是dp[i-1][j]
(表示*
匹配了s[i-1]
)或者dp[i][j-2]
(表示*
没有匹配任何字符)。 - 如果
s[i-1]
和p[j-2]
不相等,且p[j-2]
不是.
,那么dp[i][j]
只能是dp[i][j-2]
(表示*
没有匹配任何字符)。 - 另外,如果
p[j-2]
是.
且p[j-1]
是*
,那么它们可以匹配任意字符串,包括空字符串。因此,在这种情况下,dp[i][j]
还应该是dp[i-1][j]
或True
(如果模式到此结束)。但是,由于我们已经处理了s[i-1]
和p[j-2]
相等或p[j-2]
是.
的情况,所以这里只需要考虑dp[i][j-2]
或(如果i == 0
)True
。
但是,上述逻辑在处理*
时有些复杂,我们可以稍微优化一下。考虑到*
可以匹配零个或多个前面的字符,我们可以这样思考:
- 如果
s[i-1]
和p[j-2]
匹配(相等或p[j-2]
是.
),那么dp[i][j] = dp[i-1][j] || dp[i][j-1] || dp[i][j-2]
。这里dp[i-1][j]
表示将*
当作匹配了一个字符来处理,dp[i][j-1]
实际上是不合法的(因为*
必须和前面的字符一起考虑),但在这里我们可以忽略它,因为dp[i][j-2]
已经涵盖了不使用*
的情况。所以实际上我们只需要考虑dp[i][j] = dp[i-1][j] || dp[i][j-2]
。 - 如果不匹配,那么
dp[i][j] = dp[i][j-2]
(表示*
没有匹配任何字符)。
注意,当处理到dp[0][j]
(即字符串s
为空)时,我们需要特别处理。如果模式p
的当前字符是*
,那么dp[0][j]
应该是dp[0][j-2]
(因为空字符串无法匹配任何字符,但*
可以表示匹配零个字符)。
现在我们可以根据这个状态转移方程来实现代码:
def is_match(s, p):
m, n = len(s), len(p)
dp = [[False] * (n + 1) for _ in range(m + 1)]
dp[0][0] = True # 空字符串匹配空模式
# 处理 s 为空字符串,p 不为空的情况
for j in range(1, n + 1):
if p[j - 1] == '*':
dp[0][j] = dp[0][j - 2]
# 填充剩余的 dp 数组
for i in range(1, m + 1):
for j in range(1, n + 1):
if p[j - 1] in {s[i - 1], '.'}: # 当前字符匹配
dp[i][j] = dp[i - 1][j - 1]
elif p[j - 1] == '*': # 当前字符是 *
if p[j - 2] in {s[i - 1], '.'}: # * 前面的字符匹配当前 s 的字符
dp[i][j] = dp[i - 1][j] or dp[i][j - 2]
else: # * 前面的字符不匹配当前 s 的字符,只能将 * 当作匹配零个字符来处理
dp[i][j] = dp[i][j - 2]
else: # 当前字符不匹配且不是 *
dp[i][j] = False # 这里实际上不需要显式设置为 False,因为默认就是 False
return dp[m][n]
# 示例输入和输出
strings = input().split() # 输入字符串数组,空格分隔
pattern = input() # 输入字符规律
# 检查每个字符串是否与模式匹配,并收集匹配字符串的索引
matching_indices = []
for i, s in enumerate(strings):
if is_match(s, pattern):
matching_indices.append(str(i))
# 输出匹配的字符串索引,用英文逗号分隔,如果没有匹配的则输出 -1
print(','.join(matching_indices) if matching_indices else '-1')
这段代码首先定义了一个is_match
函数来实现动态规划匹配算法,然后读取输入,对每个字符串调用is_match
函数来检查是否匹配给定的模式,并收集匹配的字符串索引。最后,它输出匹配的字符串索引(用逗号分隔)或-1
(如果没有匹配的字符串)。
作为互联网求职大人和大厂的专业老师,对于准备参加校招的年轻人,我有以下几点建议:
一、深入了解行业与公司
在求职前,务必对所感兴趣的行业进行深入了解,包括行业趋势、发展前景、竞争格局等方面。同时,要研究目标公司的企业文化、业务模式、核心产品或服务,以及公司在行业中的地位和优势。这样,在面试时才能更准确地表达自己对公司和行业的认识,展现出自己的热情和专业素养。
二、精准定位个人职业方向
根据自己的兴趣、专业背景和技能特长,精准定位自己的职业方向。了解不同职位的岗位职责、任职要求和发展路径,选择与自己匹配度高的职位进行投递。这样,不仅能提高求职成功率,还能确保个人在职业发展中的优势和兴趣得到充分发挥。
三、重视简历与面试技巧
简历是求职的敲门砖,务必认真制作。简历要突出自己的教育背景、实习经历、项目经验和技能特长,注重简洁明了、重点突出。同时,要掌握面试技巧,如着装得体、表达清晰、态度积极等。在面试过程中,要保持自信、冷静和专注,积极回答面试官的问题,并展示自己的思维能力和解决问题的能力。
四、关注校招政策和流程
不同公司的校招政策和流程可能有所不同,务必关注目标公司的官方招聘信息,了解校招的时间安排、招聘流程、面试形式等。在求职过程中,要保持关注公司招聘信息的更新,及时了解面试结果和后续安排。
五、积累实习和项目经验
对于缺乏工作经验的应届生来说,实习和项目经验是提升求职竞争力的重要途径。在校期间,要积极参加各类实习项目,争取在知名企业或相关行业内积累实践经验。同时,可以参与课外科技活动或社团活动,锻炼自己的团队合作能力和领导力。
六、提升专业技能和综合素质
在求职过程中,专业技能和综合素质同样重要。要不断提升自己的专业技能水平,掌握行业前沿技术和工具。同时,要注重培养自己的综合素质,如沟通能力、解决问题的能力、创新能力等。这些能力的提升将有助于更好地适应职场环境并实现个人价值。
七、保持积极心态和耐心
求职过程中可能会遇到各种挫折和困难,但要保持积极的心态和耐心。要相信自己的能力和价值,勇敢面对挑战和竞争。同时,要做好长期准备,不要急于求成或轻易放弃。通过不断努力和尝试,最终一定能够找到适合自己的职业机会。