第一个HASH貌似写错了,总是少状态,看了别人的代码改了一下HASH,因为无法完美HASH,所以还要根据深度与节点状态判重。
Time Limit: 5000MS | Memory Limit: 65536K | |||
Total Submissions: 1361 | Accepted: 368 | Special Judge |
Description
Deterministic Final-State Automaton (DFA) is a directed multigraph whose vertices are called states and edges are called transitions. Each DFA transition is labeled with a single letter. Moreover, for each state s and each letter l there is at most one transition that leaves s and is labeled with l. DFA has a singlestarting state and a subset of final states. DFA defines a language of all words that can be constructed by writing down the letters on a path from the starting state to some final state.
Given a language with a finite set of words it is always possible to construct a DFA that defines this language. The picture on the left shows such DFA for the language consisting of three words: fix, foo, ox. However, this DFA has 7 states, which is not optimal. The DFA on the right defines the same language with just 5 states.
Your task is to find the minimum number of states in a DFA that defines the given language.
Input
The first line of the input file contains a single integer number n (1 ≤ n ≤ 5 000 ) — the number of words in the language. It is followed by n lines with a word on each line. Each word consists of 1 to 30 lowercase Latin letters from “a” to “z”. All words in the input file are different.
Output
Write to the output file a single integer number — the minimal number of states in a DFA that defines the language from the input file.
Sample Input
#1 | 3 fix foo ox |
---|---|
#2 | 4 a ab ac ad |
Sample Output
#1 | 5 |
---|---|
#2 | 3 |
#include<iostream>
#include<cstring>
#include<cstdio>
#include<string>
#include<algorithm>
#include<cmath>
using namespace std;
#define K 1111111
#define MAXN 5000*30+10
#define MAX 26
typedef long long ll;
struct Trie
{
int sz,t[MAXN][MAX];
int jud[MAXN];
void clear()
{
sz=1;
memset(t[0],-1,sizeof(t));
jud[0]=0;
}
int idx(char c)
{
return c-'a';
}
void insert(char* s,int v)
{
int u=0,n=strlen(s);
for(int i=0;i<n;i++)
{
int c=idx(s[i]);
if(t[u][c]==-1)
{
memset(t[sz],-1,sizeof(t[sz]));
jud[sz]=0;
t[u][c]=sz++;
}
u=t[u][c];
}
jud[u]=v;
}
};
Trie t;
ll hash[K];
int ID[K],dep[K];
int n;
char str[200];
bool cmp(int a,int b)
{
if(dep[a]!=dep[b]) return dep[a]<dep[b];
if(hash[a]!=hash[b]) return hash[a]<hash[b];
return t.jud[a]<t.jud[b];
}
void dfs(int u)
{
hash[u]=1;
dep[u]=0;
ll p=1;
for(int i=0;i<26;i++)
{
if(t.t[u][i]!=-1)
{
dfs(t.t[u][i]);
dep[u]=max(dep[u],dep[t.t[u][i]]+1);
//hash[u]=(hash[u]+(hash[t.t[u][i]]*26+i+1))%K;
hash[u]=hash[u]+(hash[t.t[u][i]]+(t.jud[t.t[u][i]]?K:0))*p;
}
p=p*23;
}
}
int main()
{
while(~scanf("%d",&n))
{
t.clear();
for(int i=0;i<n;i++)
{
scanf("%s",str);
t.insert(str,1);
}
dfs(0);
for(int i=0;i<t.sz;i++)
ID[i]=i;
sort(ID,ID+t.sz,cmp);
int ans=1;
for(int i=1;i<t.sz;i++)
{
if(hash[ID[i]]!=hash[ID[i-1]]||dep[ID[i]]!=dep[ID[i-1]]||t.jud[ID[i]]!=t.jud[ID[i-1]])
ans++;
}
printf("%d\n",ans);
}
return 0;
}