令S为该数字的十进制表示形式。如果n = |S| 足够小(<500左右),可以使用以下算法:
\n\n让我们从方程 A + B = C 中枚举 A 和 C(其中我们假设 wlog A > B)。我们知道它们的大小需要大致相同(加/减一位数),因此枚举可能性是三次运算(有O(n 3 )个候选者)。
\n\n对于每个候选对(A, C),我们需要检查 是否B = C - A在字符串中并且不与任何A或C子串重叠。我们可以使用以 10 为基数的算术来计算线性时间的差异。
棘手的部分是检查B是否是不与A或C重叠的子字符串。A和C将字符串分成 3 部分:
\n\nS = xAyCz\nRun Code Online (Sandbox Code Playgroud)\n\n如果我们以一种巧妙的方式枚举它们,具有固定的起始位置和递减的大小,我们可以维护部分 x 的后缀自动机以及部分 y 和 z 的反转。
\n\n现在我们可以在线性时间内检查B = C - A(或其相反)是否存在于三个部分之一中。
\n\n这种方法的时间复杂度:\xce\x98(n 4 )。
\n\n有一个变体,稍微复杂一些,但速度更快(感谢 Evgeny 指出):
\n\n运行时间:O(n 3 log n)。
\n\n更新:关于需要使用所有字符的简化版本:
\n\n我们首先意识到,如果我们以 10 为基数,我们可以在线性时间内对字符串的子字符串进行算术运算。
\n\n现在我们想要找到分裂点a < b,这样你的三个子字符串是A = s 1 ...s a,B = s a+1 ...s b和C = s b+1 ...s名词
\n\n我们可以证明a和b的候选数只有恒定数量,因为所有三个部分必须具有大致相同的大小才能使方程成立。
\n\n使用任意精度算术,我们可以轻松尝试所有候选对 (a,b),并针对每个候选对找到M = max(A,B,C)。然后只需检查M是否是其他两个数字的和。
\n\n总时间复杂度:\xce\x98(n)。
\n