hash判断子树是否相同,并且自身的终结性要相同。
代码:
#include<iostream>
#include<fstream>
using namespace std;
#define prim 99983
struct {
int end;
int p[30];
}tree[150001];
int n,m;
char c[30];
int state;
void build(char c[]){
int i,j,k;
i=1;
for(j=0;j<strlen(c);j++)
{
k=c[j]-'a';
if(tree[i].p[k]==0)
tree[i].p[k]=++state;
i=tree[i].p[k];
}
tree[i].end=1;
}
struct e{
int data;
e *next;
}hash[100000];
int f[150001];
int value[150001];
int ok(int s,int t){
int i,j,k;
for(i=0;i<26;i++)
if(tree[s].p[i]==0&&tree[t].p[i])
return 0;
else
if(tree[s].end!=tree[t].end)
return 0;
else
if(tree[s].p[i]&&tree[t].p[i]==0)
return 0;
else
if(tree[s].p[i]&&tree[t].p[i]&&f[tree[s].p[i]]!=f[tree[t].p[i]])
return 0;
return 1;
}
void dfs(int s){
int i,j,k;
k=0;
for(i=0;i<26;i++)
if(tree[s].p[i]!=0)
{
dfs(tree[s].p[i]);
k=(k+value[tree[s].p[i]]*27+i)%prim;
}
value[s]=k;
if(hash[k].next==0)
{
e *p=new e;
p->data=s;
p->next=hash[k].next;
hash[k].next=p;
f[s]=++m;
}
else
{
e*p=hash[k].next;
while(p){
if(ok(p->data,s))
{
f[s]=f[p->data];
break;
}
p=p->next;
}
if(!p)
{
e *p=new e;
p->data=s;
p->next=hash[k].next;
hash[k].next=p;
f[s]=++m;
}
}
}
void read(){
// ifstream cin("in.txt");
int i,j,k;
while(cin>>n){
m=0;
memset(tree,0,sizeof(tree));
memset(hash,0,sizeof(hash));
memset(value,0,sizeof(value));
state=1;
for(i=1;i<=n;i++)
{
// cin>>c;
scanf("%s",c);
build(c);
}
dfs(1);
cout<<m<<endl;
}
}
int main(){
read();
return 0;
}