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

如何用Java高效判断一个单词是否为NICE单词?

优化NICE单词检测的性能问题

兄弟,我太懂你这种“逻辑全对但一跑长单词用例就超时”的憋屈了!咱们直接用KMP算法里的核心思想——**部分匹配表(Next数组)**来解决,把时间复杂度从暴力的O(n²)直接降到线性的O(n),长单词也能秒出结果。

NICE单词定义

若一个单词拥有相同的真前缀(proper prefix)和真后缀(proper suffix),则该单词为NICE单词。真前缀或真后缀的长度不得与单词本身长度相同。

示例

  • manama是NICE单词,因其真前缀和真后缀均为“ma”,输出“NICE”
  • panama不是NICE单词,输出“NOT”

性能优化方案

问题根源

之前的暴力解法应该是枚举所有可能的前后缀长度(从1到单词长度-1),逐个比较前缀和后缀是否相等。这种方法在单词很长时,每次比较都要扫一遍子串,时间开销直接爆炸。

核心思路

KMP算法的Next数组专门用来记录每个位置前的子串的最长相等真前缀后缀长度。对于整个单词来说,next[单词长度-1](数组从0开始)就是我们要找的最长匹配长度——只要这个长度大于0,就说明存在符合要求的真前缀后缀,单词就是NICE的;反之则不是。

Java代码实现

public static String checkNiceWord(String word) {
    int wordLen = word.length();
    // 长度<=1的单词没有真前缀/后缀,直接返回NOT
    if (wordLen <= 1) {
        return "NOT";
    }
    
    int[] next = new int[wordLen];
    int prefixLen = 0; // 当前匹配的前缀长度
    
    // 构建Next数组
    for (int i = 1; i < wordLen; i++) {
        // 不匹配时,回退到上一个匹配的前缀位置
        while (prefixLen > 0 && word.charAt(i) != word.charAt(prefixLen)) {
            prefixLen = next[prefixLen - 1];
        }
        // 匹配成功,前缀长度+1
        if (word.charAt(i) == word.charAt(prefixLen)) {
            prefixLen++;
            next[i] = prefixLen;
        }
    }
    
    // 判断最长相等真前后缀长度是否大于0
    return next[wordLen - 1] > 0 ? "NICE" : "NOT";
}

为什么这能提速?

构建Next数组的过程只需要遍历单词一次,是线性时间复杂度O(n)。相比暴力法每次比较都要重复扫描子串,这个方法不管单词多长,都能高效完成检测——哪怕是几万字符的长单词,也能瞬间给出结果。

拿示例来说:

  • manama的Next数组最后一位是2(对应长度为2的"ma"),所以返回"NICE"
  • panama的Next数组最后一位是0,所以返回"NOT"

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 08:59:00