poj 3576
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; }