一、题目描述
给你一个字符串 s 和一个字符串列表 wordDict 作为字典。请你判断是否可以利用字典中出现的单词拼接出 s 。
注意:不要求字典中出现的单词全部都使用,并且字典中的单词可以重复使用。
二、思路
刚开始看到这个题目就想到暴力匹配法,如果字符串s的前length个字符串与wordDict里面的某一个字符串相等(length是字符串的长度),那么就将字符串s 在length之后的字符串递归调用,直到字符串s为空串,说明全部匹配成功,返回True,反之返回False。
三、代码实现
class Solution:
def wordBreak(self, s: str, wordDict: List[str]) -> bool:
if s == "": # 如果s是空,说明前面的所有的字符串都已经成功匹配了
return True
for i in wordDict:
length = len(i)
# 如果s的前length个字符串与i相等,说明匹配成功
if s[:length] == i :
# 将之后的字符串进行匹配,此时的s是code,wordDict没变化。如果之后返回的都是True,则匹配成功,返回False。
if self.wordBreak(s[length:], wordDict):
return True
# 匹配失败
return False
根据多年的经验,不出意外的话,要出意外了。超时了!!! 指数级的时间复杂度还是扛不住。
最后执行的输入
“aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab”
[“a”,“aa”,“aaa”,“aaaa”,“aaaaa”,“aaaaaa”,"aaaaa…
修改了几次,一直是超时,因为这个题在动态规划里面,所以就往这方面想。
假设, 如果 字符串 s 的后n(n是wordDick里面某个字符串的长度)位与 wordDick中的某个字符串匹配上了,且前面的几位(s的长度 - n)可以由 wordDict里面的字符串subs构成,那么肯定是匹配成功的。
假设dp数组中保存着前n位是否能由wordDict中的字符串构成,True是能,False是不能,那么:i 是字符串s的长度,n是wordDict中某个字符串的长度, 当i大于n时,dp[i] = dp[i-n] && s[i-n:i] == subs
,这个就是推导式。dp的长度应为字符串s的长度+1,dp[0]初始化为True。
总共花了一个多小时啊~~~~~~
所以 最终代码为:
class Solution:
def wordBreak(self, s: str, wordDict: List[str]) -> bool:
dp = [False] * (len(s) + 1)
dp[0] = True
for i in range(1, len(s)+1):
for j, val in enumerate(wordDict):
length = len(val)
if s[:i] == val: # 当 前i位与val相等时, 匹配成功,dp[i]设置为true
dp[i] = True
if i > length:
if s[i-length:i] == val and dp[i-length]: # 递推公式
dp[i] = True
return dp[-1]
啦啦啦啦啦啦啦啦啦啦