BZOJ 2537 [neerc2007]Language Recognition Trie树 树Hash

来源:互联网 发布:算法时代pdf下载 编辑:程序博客网 时间:2024/06/09 19:55

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2537

题目大意:
求一个包含且仅包含给定n个单词的DFA的最少状态数

题解:
建立Trie树,若某两个结点的子树完全相同且同为或同不为终止节点,则可以合并这两个子树
①
②
③

代码:

#include <bits/stdc++.h>using namespace std;#define MAXN 5005typedef 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;}
0 0
原创粉丝点击