You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何验证最长拼接单词是否完全由字典内短单词构成?

如何检查目标单词是否由字典中更短单词拼接而成

嘿,我来帮你搞定这个问题!首先得指出,你当前的tryMatch方法存在几个关键的逻辑问题,咱们先把这些坑填上,再给你靠谱的实现思路和代码。

你的现有方法的问题

  • 字符串比较错误:Java里用nextWord == s判断字符串相等是踩坑了——==比的是对象引用,不是内容,得用equals()才行。
  • 越界风险:当i是字典最后一个元素时,i+1直接会抛出IndexOutOfBoundsException,这绝对会让程序崩溃。
  • 核心逻辑不对:contains()只能判断子串存在,但没法保证这些子串能无重叠、完整拼接出目标单词。举个例子:如果目标单词是"applepie",字典里有"app"和"pie",你的方法会返回true,但实际上"app"+"pie"拼出来是"apppie",根本不是"applepie",但你的方法会误判。
  • 统计逻辑无意义:contaned >1的判断完全站不住脚——比如一个单词可能只需要两个短单词拼接(比如"a"+"b"拼成"ab"),但也可能需要多个,更关键的是,就算统计到多个子串存在,也不代表它们能凑成完整的目标单词。

正确的实现思路

既然你的字典已经按长度降序排列,咱们可以利用这个特性优化检查过程:

  1. 先把字典转成HashSet,这样判断某个单词是否存在的时间复杂度是O(1),效率高很多。同时要排除目标单词本身,因为题目要求用更短的单词拼接。
  2. 用两种靠谱的方式实现检查:
    • 递归+记忆化:遍历所有可能的拆分点,检查前缀是否在字典里,然后递归检查剩下的后缀能不能被拆分。用记忆化缓存避免重复计算,提升效率。
    • 动态规划:用一个布尔数组记录子串是否能被拼接,从短到长逐步推导整个单词是否符合要求,适合处理较长的单词,不会有栈溢出问题。

代码实现

方法1:递归+记忆化(适合单词长度不算特别长的场景)

import java.util.List;
import java.util.Set;
import java.util.HashSet;

public class Solution {
    private Set<String> wordSet;
    private Boolean[] memo;

    public boolean tryMatch(String s, List<String> dictionary) {
        // 转成Set方便快速查找,同时移除目标单词本身
        wordSet = new HashSet<>(dictionary);
        wordSet.remove(s);
        // 记忆化数组,缓存子问题的结果
        memo = new Boolean[s.length() + 1];
        return canSplit(s, 0);
    }

    private boolean canSplit(String s, int start) {
        // 走到字符串末尾,说明拼接成功
        if (start == s.length()) {
            return true;
        }
        // 已经计算过这个子问题,直接返回缓存结果
        if (memo[start] != null) {
            return memo[start];
        }
        // 遍历所有可能的拆分点
        for (int end = start + 1; end <= s.length(); end++) {
            String prefix = s.substring(start, end);
            // 前缀在字典里,且后缀也能被拆分的话,就返回true
            if (wordSet.contains(prefix) && canSplit(s, end)) {
                memo[start] = true;
                return true;
            }
        }
        // 所有拆分方式都不行,标记为false
        memo[start] = false;
        return false;
    }
}

方法2:动态规划(适合长单词,避免递归栈溢出)

import java.util.List;
import java.util.Set;
import java.util.HashSet;

public class Solution {
    public boolean tryMatch(String s, List<String> dictionary) {
        Set<String> wordSet = new HashSet<>();
        // 只保留比目标单词短的单词,减少集合大小
        for (String word : dictionary) {
            if (word.length() < s.length()) {
                wordSet.add(word);
            }
        }
        int n = s.length();
        // dp[i]表示s的前i个字符组成的子串能否被拼接
        boolean[] dp = new boolean[n + 1];
        dp[0] = true; // 空串是基础情况,默认可以拼接

        for (int i = 1; i <= n; i++) {
            for (int j = 0; j < i; j++) {
                // 如果前j个字符能拼接,且j到i的子串在字典里,就标记dp[i]为true
                if (dp[j] && wordSet.contains(s.substring(j, i))) {
                    dp[i] = true;
                    break; // 找到一种方式就够了,不用继续遍历
                }
            }
        }
        return dp[n];
    }
}

额外优化小技巧

因为你的字典已经按长度降序排列,在构建wordSet的时候,我们可以直接跳过长度大于等于目标单词的单词(除了目标单词本身,不过我们已经排除了),这样能减少集合的大小,提升查找和遍历的效率,就像上面动态规划代码里做的那样。

内容的提问来源于stack exchange,提问作者Timoha Timoshenko

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:14:08