POJ 1635 树的最小表示法/HASH

 

题目链接:http://poj.org/problem?id=1635

题意:给定两个由01组成的串,0代表远离根,1代表接近根。相当于每个串对应一个有根的树。然后让你判断2个串构成的树是否是同构的。

思路:首先根据01串构造出树,然后求树的最小表示法判断同构。 详情参照:https://www.byvoid.com/blog/directed-tree-bracket-sequence/ 

 

#define _CRT_SECURE_NO_DEPRECATE
#include<iostream>
#include<cstring>
#include<algorithm>
#include<string>
#include<cstdio>
#include<vector>
using namespace std;
typedef long long int LL;
const int MAXN=3000+5;
int fa[MAXN];
char strA[MAXN],strB[MAXN];
vector<int>treeA[MAXN],treeB[MAXN];
void build(char *s,vector<int>tree[MAXN]){
    int hashNum=1,now=0,len=strlen(s);
    for(int i=0;i<MAXN;i++){
        tree[i].clear();
    }
    for(int i=0;i<len;i++){
        if(s[i]=='0'){
            fa[hashNum]=now;
            tree[now].push_back(hashNum);
            now=hashNum++;
        }
        else{
            now=fa[now];
        }
    }
}
string dfs(int now,vector<int>tree[MAXN]){
    vector<string>HashC;
    for(int i=0;i<tree[now].size();i++){
        HashC.push_back(dfs(tree[now][i],tree));
    }
    string Hash="(";
    sort(HashC.begin(),HashC.end());
    for(int i=0;i<HashC.size();i++){
        Hash+=HashC[i];
    }
    Hash+=")";
    return Hash;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--){
        scanf("%s",strA); scanf("%s",strB);
        memset(fa,0,sizeof(fa));build(strA,treeA);
        memset(fa,0,sizeof(fa));build(strB,treeB);
        if(dfs(0,treeA)==dfs(0,treeB)){
            printf("same\n");
        }
        else{
            printf("different\n");
        }
    }
    return 0;
}

 

思路2:HASH,思路参照:集训队论文:杨弋《Hash在信息学竞赛中的一类应用》

题目卡的比较死。 参数不好拿捏。最好进行Double HASH比较保险

#define _CRT_SECURE_NO_DEPRECATE
#include<iostream>
#include<cstring>
#include<algorithm>
#include<string>
#include<cstdio>
#include<vector>
using namespace std;
typedef long long int LL;
typedef unsigned int uint;
const int MAXN=3000+5;
const int MODF=1e9+7;
const int MODS=1e9+7;
int fa[MAXN],HF[MAXN],HS[MAXN];
char strA[MAXN],strB[MAXN];
vector<int>treeA[MAXN],treeB[MAXN];
void build(char *s,vector<int>tree[MAXN]){
    int hashNum=1,now=0,len=strlen(s);
    for(int i=0;i<MAXN;i++){
        tree[i].clear();
    }
    for(int i=0;i<len;i++){
        if(s[i]=='0'){
            fa[hashNum]=now;
            tree[now].push_back(hashNum);
            now=hashNum++;
        }
        else{
            now=fa[now];
        }
    }
}
pair<int,int> dfs(int now,vector<int>tree[MAXN]){
    int HashNumF=1,HashNumS=1;
    vector<pair<int,int> >HashC;
    for(int i=0;i<tree[now].size();i++){
        HashC.push_back(dfs(tree[now][i],tree));
    }
    sort(HashC.begin(),HashC.end());
    for(int i=0;i<HashC.size();i++){
        HashNumF=((HashNumF^HashC[i].first)*HF[i])%MODF;
        HashNumS=((HashNumS^HashC[i].second)*HS[i])%MODS;
    }
    return make_pair(HashNumF%MODF,HashNumS%MODS);
}
int main()
{
    for(int i=0;i<MAXN;i++){
        HF[i]=rand()%MODF;
        HS[i]=rand()%MODS;
    }
    int t;
    scanf("%d",&t);
    while(t--){
        scanf("%s",strA); scanf("%s",strB);
        memset(fa,0,sizeof(fa));build(strA,treeA);
        memset(fa,0,sizeof(fa));build(strB,treeB);
        pair<int,int>TA=dfs(0,treeA);
        pair<int,int>TB=dfs(0,treeB);
        if(TA.first==TB.first&&TA.second==TB.second){
            printf("same\n");
        }
        else{
            printf("different\n");
        }
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/kirito520/p/5639722.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值