假设我有以下列表列表:
x = [[1, 2, 3, 4, 5, 6, 7], # sequence 1
[6, 5, 10, 11], # sequence 2
[9, 8, 2, 3, 4, 5], # sequence 3
[12, 12, 6, 5], # sequence 4
[5, 8, 3, 4, 2], # sequence 5
[1, 5], # sequence 6
[2, 8, 8, 3, 5, 9, 1, 4, 12, 5, 6], # sequence 7
[7, 1, 7, 3, 4, 1, 2], # sequence 8
[9, 4, 12, 12, 6, 5, 1], # sequence 9
]
本质上,对于列表中任何位置包含目标编号5
(即target=5
)的任何列表,长度为{{1}的最常见N=2
个子序列是什么}}?
因此,条件是:
M=4
,则我们将完全忽略该列表target
,则我们将完全忽略列表M
,但M
不在target
位置,则我们将其忽略(但如果Mth
位于{{ 1}}位置)target
长于Mth
,并且L
位于M
位置target
i = M + 1 {{1 }} i = M + 2 i=M
i = L (or
M position, or
目标在子序列中处于最终位置因此,使用列表列表示例,我们将计算以下子序列:
position, ...,
当然,我们想要的是频率最高的position) then we count the subsequence of length
子序列。因此,按计数,where
和subseqs = [[2, 3, 4, 5], # taken from sequence 1
[2, 3, 4, 5], # taken from sequence 3
[12, 12, 6, 5], # taken from sequence 4
[8, 8, 3, 5], # taken from sequence 7
[1, 4, 12, 5], # taken from sequence 7
[12, 12, 6, 5], # taken from sequence 9
]
是最常见的两个序列。如果N=2
,则将返回所有子序列([2, 3, 4, 5]
),因为并列第三个。
重要
这是超级简化的,实际上是我的实际序列表
[12, 12, 6, 5]
和N=3
可以小到1或大到100 我的问题是:
subseqs
和N
始终小于100,是否有一种有效的数据结构可以进行快速查询?M
和N
的各种组合执行这种分析的算法?我查看了后缀树,但必须滚动自己的自定义版本,才能接近我需要的版本。M
,N
和M
(其中target
,{{ 1}}和`M <= 100)。如何有效地做到这一点?答案 0 :(得分:1)
扩展我的评论。这是一个草图,您可以使用现成的后缀数组来解决此问题:
1)反转并用停止符号将列表连接起来(我在这里使用0)。
[7, 6, 5, 4, 3, 2, 1, 0, 11, 10, 5, 6, 0, 5, 4, 3, 2, 8, 9, 0, 5, 6, 12, 12, 0, 2, 4, 3, 8, 5, 0, 5, 1, 0, 6, 5, 12, 4, 1, 9, 5, 3, 8, 8, 2, 0, 2, 1, 4, 3, 7, 1, 7, 0, 1, 5, 6, 12, 12, 4, 9]
2)构建一个suffix array
[53, 45, 24, 30, 12, 19, 33, 7, 32, 6, 47, 54, 51, 38, 44, 5, 46, 25, 16, 4, 15, 49, 27, 41, 37, 3, 14, 48, 26, 59, 29, 31, 40, 2, 13, 10, 20, 55, 35, 11, 1, 34, 21, 56, 52, 50, 0, 43, 28, 42, 17, 18, 39, 60, 9, 8, 23, 36, 58, 22, 57]
3)构建LCP array。 LCP数组将告诉您一个后缀与其后缀数组中的邻居共有多少个数字。但是,遇到停止符号时,您需要停止计数
[0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 2, 1, 1, 0, 2, 1, 1, 2, 0, 1, 3, 2, 2, 1, 0, 1, 1, 1, 4, 1, 2, 4, 1, 0, 1, 2, 1, 3, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 2, 1, 2, 0]
4)查询进入时(target = 5,M = 4),您在后缀数组中搜索目标的第一个匹配项,并扫描相应的LCP数组,直到后缀的起始数目发生变化。下面是LCP数组的一部分,它与所有以5开头的后缀相对应。
[..., 1, 1, 1, 4, 1, 2, 4, 1, 0, ...]
这告诉您有两个长度为4的序列出现两次。使用索引刷过一些细节,您可以找到序列并将其还原以得到最终结果。
复杂度
前两个步骤是离线进行的。从技术上讲,查询是O(n)(由于步骤4),但是常数很小(0.0001)。