题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2537
题目大意:
求一个包含且仅包含给定
n
个单词的
题解:
建立
Trie
树,若某两个结点的子树完全相同且同为或同不为终止节点,则可以合并这两个子树
代码:
#include <bits/stdc++.h>
using namespace std;
#define MAXN 5005
typedef unsigned long long ll;
int n;
char buf[35];int len;
struct Node
{
int next[26];
int end;
int &operator[](int x){return next[x];}
}tr[MAXN*30];
int tot;
struct Hash
{
ll val;
int next;
}hash[MAXN*30];
const int MOD=(1<<15)-1;
int head[MOD];
int cnt;
void Addhash(const ll &val)
{
int tmp=val&MOD;
hash[++cnt].val=val;
hash[cnt].next=head[tmp];
head[tmp]=cnt;
}
bool Query(const ll &val)
{
int tmp=val&MOD;
for(int i=head[tmp];i;i=hash[i].next)
if(hash[i].val==val)
return 1;
return 0;
}
ll DFS(int loc)
{
ll re=0;
for(int i=0;i<26;i++)
if(tr[loc][i])
re=re*13131+DFS(tr[loc][i])*(i+628)+i+628;
if(tr[loc].end) re=re*13131+1029;
if(Query(re)) tot--;
else Addhash(re);
return re;
}
int main()
{
scanf("%d",&n);
for(int now,i=1;i<=n;i++)
{
scanf("%s",buf);len=strlen(buf);
now=0;
for(int x,j=0;j<len;j++)
{
x=buf[j]-'a';
if(!tr[now][x]) tr[now][x]=++tot;
now=tr[now][x];
}
tr[now].end=1;
}
DFS(0);
printf("%d\n",tot+1);
return 0;
}