我试图构建一个后缀特里结构,并且由于严格的要求,必须在内存中进行索引。
编辑:这个问题是不是树本身,但实际上我读文件的方式。
我试图构建一个后缀特里结构,并且由于严格的要求,必须在内存中进行索引。
编辑:这个问题是不是树本身,但实际上我读文件的方式。
如果你传递整个文本文件作为一个string
,你可以很容易碰到内存不足的异常与你的第一个循环!
// imagine if s.Length was 100k or so
for (int i = 0; i < s.Length; i++)
{
AddString(s.Substring(i, s.Length-i));
}
当读取文件,构建线索,你需要拆分每一行,并可能正常化的特点:
string line;
while (null != (line = reader.ReadLine()))
{
string[] parts = line.Split(' ', ',', '.', '!', '\t', '?'); // naive
foreach (string part in parts)
{
if (part.Length > 0)
{
// make each string uppercase so as to avoid Hello and hello being
// two trie entries
trie.AddSuffix(part.ToUpperInvariant());
}
}
}
例如(从输出dir /bc:\windows
):
A
D
D
I
N
S
E
D
P
P
C
O
M
P
A
T
P
A
T
C
H
...
为了适当地处理更大的文件,更紧凑的线索结构是可取的。 我只想有存储在一个单独的字典非共享后缀:
// If you add a character, but there is no entry in m_children
// just park the tail end of it here
Dictionary<char, string> m_tails;
然后,您可以移动每个字符的逻辑在AddString
的的SuffixNode
:
public void AddString(string s)
{
if (s.Length == 0) return;
char c = s[0];
if (m_children.ContainsKey(c))
{
if (s.Length > 1) m_children[c].AddString(s.Substring(1));
}
else if (m_tails.ContainsKey(c))
{
SuffixNode node = new SuffixNode();
node.AddString(m_tails[c]);
if (s.Length > 1) node.AddString(s.Substring(1));
m_children.Add(c, node);
m_tails.Remove(c);
}
else
{
m_tails.Add(c, s.Length > 1 ? s.Substring(1) : "");
}
}
现在你有线索,这将大大减少儿童数量的更加紧凑版本SuffixNode
对于任何给定的语料库创建秒。 返回到dir /bc:\windows
例子,我们可以看到在节点实用的还原:
A
P
P
COMPAT
PATCH
I
T
I
O
N
S
...
此时你的线索有更高效的表现。 留给你的决定如何,以确保查找准确处理终端节点表示。