我正在寻找高性能算法来检查我是否可以使用给定的一组子串进行重建给定的字符串。更多细节:

让我们说我们的字符串是通过字母 $ \ sigma $

输入

  • 一个字符串 $ s \ in \ sigma ^ * $
  • 一个有限的字符串 $ a={a_1,a_2,...,a_n \} \ subset \ sigma ^ * $

输出

  • 是否 $ \存在m:\存在b_1,b_2,\ ldots,b_m \在a:b_1 + b_2 + \ cdots + b_m= s $

其中 $ + $ 是字符串连接。

例如,如果 $ s= {} $ $ abcd $ ”和 $ a={$ “ $ ab $ $,$ < / span>“ $ cd $ $,$ $ ac $ $ \} $ ,答案是真的。 出于此问题的目的,假设 $ a $ 中的字符串可以在必要时重复使用多次。

有帮助吗?

解决方案

如果在 $ a $ 中,则可以使用动态编程解决:首先,在 $中存储字符串一个$ 在前缀树中(只是一个反驳的后缀树 link $ s [i:end] $ 可以从 $ a $ :let $ \ ell $ 是字符串的长度,并且wlog假设 $ s $ s $ $ \ $$ $ a \ gets a \ cup \ {\ $ \} $ 。 Moroever,让 $ m [i] \ in \ {0,1 \} $ 表示 $ s [i:\ ell] $ 可以由 $ a $ 中的元素构建。 initialize $ m [i] \ gets \ idty $ $ i= 0,\ dots,\ ell-1 $ < / span>和 $ m [\ ell]= 1 $ (因为 $ s [\ ell]=$$ < / span>)。 现在,假设 $ f(i)$ 是递归计算 $ m [i] $ 的函数它已经没有计算过。当<跨度类=“math-container”> $ f(i)$ 调用时,从 $ a $ 的后缀树的根目录开始,遍历 $ s [i],s [i + 1],s suffix tree上的s [i + 1],\ dot $ 直到索引 $ J $ ,使得相应的节点位于 $ a $ ,递归调用 $ f(j) $ 。如果返回 $ 1 $ ,set $ m [i]= 1 $ 并返回 $ 1 $ 。否则,重复与 $ s [j + 1],s [j + 2],\ dots $ 的遍历进程,直到 $ 或达到叶子。如果没有成功,则设置 $ m [i]= 0 $ 并返回 $ 0 $ 。要确定问题,请调用 $ f(1)$ 。最坏的情况是复杂性是 $ \ ell d $ ,带 $ d $ 是深度后缀树( $ a $ ),加上前缀树的成本。

将避免在许多情况下的最坏情况场景,因为找到了一个解决方案后递归呼叫搜索停止。所以在实践中, $ \ ell d $ 部分可能会少得多。根据 $ ,后缀树的构造可能是昂贵的。但是,如果 $ a $ 用于多个字符串 $ s $ ,则成本摊销。如果 $ a $ 真的很大,而 $ s $ 很短,它可能更好地排序元素 $ a $ ,并执行二进制搜索而不是遍历。

许可以下: CC-BY-SA归因
不隶属于 cs.stackexchange
scroll top