题目描述

原题:521. 最长特殊序列 Ⅰ。

给定两个小写英文字母字符串 a、b。特殊子序列是某个字符串的子序列,但不是另一个字符串的子序列。返回最长长度;不存在返回-1。输入字符为小写英文字母。

示例 1:

输入:a = "abc", b = "abd"
输出:3
解释:"abc" 是自身的子序列,但不是 "abd" 的子序列,长度为 3。

示例 2:

输入:a = "abc", b = "abc"
输出:-1
解释:两个字符串相同,任意一个的子序列也一定是另一个的子序列。

提示:

  • a、b 只含小写英文字母;子序列可以不连续,但必须保持原字符顺序。不存在特殊子序列时返回 -1。

题意分析

从两个输入字符串中的某一个选出一条子序列,要求它不能同时成为另一个字符串的子序列,返回这种特殊子序列的最长长度。子序列可以删除字符,但必须保留剩余字符的原有顺序;也允许一个字符都不删,直接选择整串。

要求只属于其中一个输入,而不是两者共同拥有。不存在任何符合条件的子序列时返回 -1,不能用零表示无解。

解法:比较整串是否相等

核心思路

[!blue]

若两个字符串完全相同,它们能生成的全部子序列也完全相同。从任意一侧选出的序列,另一侧同样拥有,因此不存在特殊子序列,直接返回 -1。

若两个字符串长度不同,选择较长的完整字符串即可。它当然是自己的子序列,而较短的字符串不可能包含比自身还长的子序列,所以这个候选必然只属于较长的一侧。

若长度相同但内容不同,任意选择其中一个整串也合法。要从另一个等长字符串中选出相同长度的子序列,就必须保留全部字符,结果只能是另一个原串;既然两串不同,就不可能相互包含。

因此只要两串不相等,较长输入的整串就已经给出了长度为 max(a.length, b.length) 的合法答案。任何子序列又都不可能超过其来源字符串长度,这个候选同时达到答案上界,所以无需枚举更短的子序列。

解题步骤

  1. 比较两个字符串的完整内容。
  2. 内容相同则返回 -1。
  3. 内容不同则返回两个长度的较大值。

代码实现

class Solution {
    public int findLUSlength(String a, String b) {
        return a.equals(b) ? -1 : Math.max(a.length(), b.length());
    }
}
func findLUSlength(a, b string) int {
    if a == b {
        return -1
    }
    return max(len(a), len(b))
}

复杂度分析

  • 时间复杂度:最坏 $O(m)$,m 为较长字符串长度,主要用于相等判断。长度不同时可以直接判为不相等;长度相同时最坏需要逐字符比较。
  • 空间复杂度:$O(1)$,只比较字符串并读取长度,不生成候选子序列。

关键点总结

[!green]

  • 整个输入也是它自己的子序列,可以先尝试长度最大的候选。
  • 等长字符串互为完整子序列,当且仅当内容相同。
  • 非相等时已有候选达到最大可能长度,相等时所有子序列都不符合要求。

易错点总结

[!yellow]

  • 只比较长度是否相等,会漏掉等长但内容不同的合法情况。
  • 把目标理解为最长公共子序列,求到的是两个输入都拥有的内容,方向相反。
  • 以为子序列必须删除至少一个字符,会错过直接选整串的最优答案。
  • Java 用 == 判断字符串内容,会混淆对象引用与字符是否相同;这里使用 equals。
  • 两串相同时返回零,未遵循题目无解时返回 -1 的约定。

相似题目

题目 难度 关联与区别
522. 最长特殊序列 II 中等 从两个字符串扩展到多个字符串后,不能只比较相等,还要检查候选是否为任意其他串的子序列。
转载与许可
作者
链接 https://hgnulb.github.io/blog/2026/48762050
许可 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处!