如何可持久化
数据结构——Trie字典树
可持久化,即能访问曾经的内容,最简单的办法是每次更新直接把以前的内容复制到一个新的地方。然而,这样很浪费内存,因为曾经的节点大部分没必要再复制一遍。
更好的办法是每一次都额外创建被更新的节点,而不动原来的节点,并记录每一次更新所产生的新的根节点。
自己画的,有点丑
流程
设当前版本为history
- 令 p = root[histroy - 1],q = root[histroy ],i = 0
- 令 c 取遍 字符集,ch[q,c] = ch[p,c] (ch[0,c] = 0)
- ch[q,s[i]] = 新节点
- 令 p = ch[p,s[i]],q = ch[q,s[i]],i = i+1
- 重复2至4,直到 i = 字符串长度 - 1
实现
class Sustainable_Trie{
private:
int tot;
int ch[65536][26];
bool com_str[1024];
int root[256];
int history; //记录现在是第几个版本
public:
Sustainable_Trie()
{
history = 0;
tot = 0;
memset(ch,0,sizeof(ch));
memset(com_str,0,sizeof(com_str));
}
void insert(string s)
{
history++;
root[history] = ++tot;
int len = s.length();
int p = root[history-1],q = root[history];
for(int i = 0;i < len;i++)
{
int c = s[i]-'a';
for(int j = 0;j < 26;j++) ch[q][j] = ch[p][j]; //复制上一个版本的该状态的转移
ch[q][c] = ++tot; //将这个版本的该字符转移改为一个新节点
p = ch[p][c];
q = ch[q][c];
}
com_str[q]=true;
}
bool hasprefix(int k,string s)
{
int len = s.length();
int u = root[k];
bool ret = false;
for(int i = 0;i < len;i++)
{
int c = s[i]-'a';
if(!ch[u][c]) return false;
u = ch[u][c];
if(com_str[u]) return true;
}
}
bool isprefix(int k,string s)
{
int len = s.length();
int u = root[k];
bool ret = false;
for(int i = 0;i < len;i++)
{
int c = s[i]-'a';
if(!ch[u][c]) return false;
u = ch[u][c];
}
return true;
}
};