我有一组树的节点被标记(但不是唯一的)。具体来说,树来自一组解析过的句子(见http://en.wikipedia.org/wiki/Treebank)。我希望从集合中提取最常见的子树 - 性能不是(还)一个问题。我要感谢算法(理想情况下是Java)或指向为树库执行此操作的工具的指针。请注意,子节点的顺序很重要。
编辑 @mjv。我们正在一个有限的领域(化学)工作,这个领域有一种程式化的语言,所以树木的数量并不大 - 可能与儿童的读者类似。 “猫坐在垫子上”的简单树。
<sentence>
<nounPhrase>
<article/>
<noun/>
</nounPhrase>
<verbPhrase>
<verb/>
<prepositionPhrase>
<preposition/>
<nounPhrase>
<article/>
<noun/>
</nounPhrase>
</prepositionPhrase>
</verbPhrase>
</sentence>
这里的句子包含两个相同的词性小树(实际的标记“cat”。“mat”在匹配时并不重要)。所以算法需要检测到这一点。请注意,并非所有nounPhrases都相同 - “大黑猫”可能是:
<nounPhrase>
<article/>
<adjective/>
<adjective/>
<noun/>
</nounPhrase>
句子的长度会更长 - 在15到30个节点之间。我希望从1000棵树中获得有用的结果。如果这不超过一天左右,那是可以接受的。
显然,树越短越频繁,因此名词Phhrase将非常普遍。
编辑如果要通过展平树来解决这个问题,那么我认为它与最长公共子串相关,而不是最长公共序列。但请注意,我不一定只想要最长的 - 我想要一个足够长的列表,以便“有趣”(标准尚未确定)。
答案 0 :(得分:3)
我认为,虽然你说性能还不是问题,但这是一个NP难题,所以永远不可能让它变得快速。如果我理解正确,您可以将此视为Longest common subsequence问题的变体;如果你将你的树变成像
这样的直线序列(nounphrase)(DOWN)(article:the)(adjective:big)(adjective:black)(noun:cat)(UP)
然后你的问题变成了LCS。
Wikibooks有一个LCS here
的java实现答案 1 :(得分:3)
在集合中查找最常见的子树,创建子树的紧凑形式,然后迭代每个子树并使用哈希集来计算它们的出现次数。 30个节点对于完美的哈希来说太大了 - 每个节点只有大约一位,你需要那么多来表明它是兄弟姐妹还是孩子。
该问题不是LCS - 最常见的序列与最长的公共子序列无关。最常见的子树是发生最多的子树。
对于长度为L的N个树,最坏情况应为O(N L ^ 2)(假设测试包含L个节点的子树的相等性是O(L))。
答案 2 :(得分:2)
这是计算机科学中一个众所周知的问题,有效的解决方案。
以下是一些相关的参考资料:
Kenji Abe,Shinji Kawasoe,Tatsuya Asai,Hiroki Arimura,Setsuo Arikawa,半结构化数据的优化子结构发现,Proc。第六届欧洲数据库知识发现原理与实践会议(PKDD-2002),LNAI 2431,Springer-Verlag,2002年8月1日至14日。
Mohammed J. Zaki,在森林中有效挖掘频繁树木,第八届ACM SIGKDD知识发现和数据挖掘国际会议,2002年7月。
或者,如果您只想要快速代码,请转到此处: FREQT (将xml转换为S表达式不应该给你带来太多问题,并留给读者练习)
答案 3 :(得分:1)
在这种情况下,我发现名为gspan的工具非常有用。可在http://www.cs.ucsb.edu/~xyan/software/gSpan.htm免费下载。它的带有matlab接口的c ++版本位于http://www.nowozin.net/sebastian/gboost/