POJ 1635 Subway tree systems Hash法判断有根树是否同构

Hash在信息学竞赛中的一类应用 中的某道例题

"不难想到的算法是使用两个字符串分别表示两棵树,但是如果使用Hash的话应该怎么做呢? 
可以使用一种类似树状递推的方法来计算Hash值: 

对于一个节点v,先求出它所有儿子节点的Hash值,并从小到大排序,记作H1,H2,„,HD。那么v的Hash值就可以计算为:  

(((a * p) ^ H1 mod q) * p ^ H2 mod q).....

 换句话说,就是从某个常数开始,每次乘以p,和一个元素异或,再除以q取余,再乘以p,和下一个元素异或,除以q取余„„一直进行到最后一个元素为止。最后把所得到的结果乘以b,再对q取余。"


#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <set>
#include <vector>
#include <string>
#include <queue>
#include <deque>
#include <bitset>
#include <list>
#include <cstdlib>
#include <climits>
#include <cmath>
#include <ctime>
#include <algorithm>
#include <stack>
#include <sstream>
#include <numeric>
#include <fstream>
#include <functional>

using namespace std;

#define MP make_pair
#define PB push_back
typedef long long LL;
typedef unsigned long long ULL;
typedef vector<int> VI;
typedef pair<int,int> pii;
const int INF = INT_MAX / 3;
const double eps = 1e-8;
const LL LINF = 1e17;
const double DINF = 1e60;
const int maxn = 3005;
const int C = 12345, p = 67890, q = 1e9 + 7;
char str1[maxn], str2[maxn];
VI ch[maxn], hash[maxn];
int fa[maxn];

int dfs(int now) {
    int m = ch[now].size();
    if(m == 0) return C;
    for(int i = 0;i < m;i++) {
        hash[now].PB(dfs(ch[now][i]));
    }
    sort(hash[now].begin(),hash[now].end());
    int ret = C;
    for(int i = 0;i < m;i++) {
        ret = (ret * p) ^ hash[now][i] % q;
    }
    return ret;
}

int gethash(char *str) {
    memset(fa,0,sizeof(fa));
    int len = strlen(str), u = 0, sz = 1;
    for(int i = 0;i < len;i++) {
        ch[i].clear(); hash[i].clear();
    }
    for(int i = 0;i < len;i++) {
        if(str[i] == '0') {
            ch[u].PB(sz);
            fa[sz] = u;
            u = sz++;
        }
        else {
            u = fa[u];
        }
    }
    return dfs(0);
}

int main() {
    int T; scanf("%d",&T);
    while(T--) {
        scanf("%s%s",str1,str2);
        if(gethash(str1) == gethash(str2)) {
            puts("same");
        }
        else puts("different");
    }
    return 0;
}

  

posted @ 2014-09-02 21:22  acm_roll  阅读(320)  评论(0编辑  收藏  举报