- admin's blog
【模板】字典树
- @ 2024-3-24 11:32:13
【模板】字典树
前缀树。
字符串的常用算法,后续的很多算法都是构建一颗奇奇怪怪的字典树。
Tree
在结构体树中构建节点信息,看题目要求来确定有哪些标记。如结束标记vis等等。
struct strtree
{
bool vis=0;
int son[30];
int len;
}tree[N];
insert
字典树的叶子节点插入。首先我们从树的起点和字符串的起点开始。沿着树和字符串走动。
当走到某一处的时候,如果该位置没有建立过,那么就新建一个节点,并让他的父亲指向该节点。
void insert(string x)
{
int now=0,i=0;
while( i<s.length()-1 )
{
if( !tree[now].son[ x[i]-'a' ] )
{
tree[now].son[ x[i]-'a' ]=++cnt;
}
now=tree[now].son[ x[i]-'a' ];
i++;
}
if( !tree[now].son[ x[i]-'a' ] )
{
tree[now].son[ x[i]-'a' ]=++cnt;
}
now=tree[now].son[ x[i]-'a' ];
tree[now].vis=1;
}
dfs树
这部分的内容和建树的内容相差不大,主要是体现在结果的统计。
void dfs(int x)
{
tree[x].len+=tree[x].vis;
ans=max( ans,tree[x].len );
for(int i=0;i<26;i++)
{
if( tree[x].son[i] )
{
tree[ tree[x].son[i] ].len=tree[x].len;
dfs( tree[x].son[i] );
}
}
}
Code
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+12;
int ans=0,n,cnt;
string s;
struct strtree
{
bool vis=0;
int son[30];
int len;
}tree[N];
void insert(string x)
{
int now=0,i=0;
while( i<s.length()-1 )
{
if( !tree[now].son[ x[i]-'a' ] )
{
tree[now].son[ x[i]-'a' ]=++cnt;
}
now=tree[now].son[ x[i]-'a' ];
i++;
}
if( !tree[now].son[ x[i]-'a' ] )
{
tree[now].son[ x[i]-'a' ]=++cnt;
}
now=tree[now].son[ x[i]-'a' ];
tree[now].vis=1;
}
void dfs(int x)
{
tree[x].len+=tree[x].vis;
ans=max( ans,tree[x].len );
for(int i=0;i<26;i++)
{
if( tree[x].son[i] )
{
tree[ tree[x].son[i] ].len=tree[x].len;
dfs( tree[x].son[i] );
}
}
}
int main(){
cin>>n;
while( n-- )
{
cin>>s;
insert(s);
}
dfs(0);
cout<<ans;
}