您的位置:首页 > 其它

poj 1635 树同构 记录成长历程

2012-12-11 20:48 253 查看
主要算法来自于杨弋的论文1,原始暴力代码,直接TLE
#include <iostream>
#include <cstdio>
#include <cstring>
#define LMT 3003
using namespace std;
//方法有问题,TLE
char str1[LMT],str2[LMT];
int  stack[LMT],len1[LMT],len2[LMT],con1[LMT],con2[LMT],tree1[LMT][LMT],
tree2[LMT][LMT];
bool vis[LMT];
void dfs1(int u)
{
    con1[u]=1;
    for(int i=0;i<len1[u];i++)
    {
        dfs1(tree1[u][i]);
        con1[u]+=con1[tree1[u][i]];
    }
}
void dfs2(int u)
{
    con2[u]=1;
    for(int i=0;i<len2[u];i++)
    {
        dfs2(tree2[u][i]);
        con2[u]+=con2[tree2[u][i]];
    }
}
void kill(int u)
{
    for(int i=0;i<len2[u];i++)
    vis[tree2[u][i]]=0;
}
void build(char str[],int len[],bool t)
{
    int top=0,u=0,all=1;
    memset(len,0,sizeof(len));
    for(int i=0;str[i];i++)
    switch(str[i])
    {
        case '0':
        if(!t)
          tree1[u][len[u]++]=all;
        else  tree2[u][len[u]++]=all;
        stack[top++]=u;
        u=all++;
        break;
        case '1':u=stack[--top];break;
    }
   if(!t)
    dfs1(0);
   else dfs2(0);
}
bool compare(int a,int b)
{
    if(len1[a]!=len2[b]||con1[a]!=con2[b])
          return 0;
    for(int i=0,j;i<len1[a];i++)
    {
        int x=tree1[a][i],y;
        for( j=0;j<len2[b];j++)
        if(0==vis[tree2[b][j]])
        {
            y=tree2[b][j];
            if(compare(x,y))
            {
                vis[y]=1;
                break;
            }
            else kill(y);
        }
        if(j>=len2[b])
        {
            kill(b);
            return 0;
        }
    }
    kill(b);
    return 1;
}
int main(void)
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%s%s",str1,str2);
        if(strlen(str1)!=strlen(str2))
        {
            printf("different\n");
            continue;
        }
        build(str1,len1,0);
        build(str2,len2,1);
        memset(vis,0,sizeof(vis));
        if(compare(0,0)) printf("same\n");
        else printf("different\n");
    }
    return 0;
}
2.某大神的做法,可是那个算法对mod值取值的要求极高,至今不知道mod值的取法
#include <iostream>
#include<cstdio>
#include <algorithm>
#define mod 19997
#define LMT 3002
using namespace std;
char str1[LMT],str2[LMT];
int hash[LMT<<2];
char *p;
int dfs(int u)
{
    int sum=hash[u+LMT];
    while(*p&&*p++=='0')
        sum=(sum+hash[u]*dfs(u+1))%mod;
        return (sum*sum)%mod;
}
void init(void)
{
    for(int i=0;i<LMT<<2;i++)
       hash[i]=rand()%mod;
}
int main()
{
    int T,x,y;
    scanf("%d",&T);
            init();
    while(T--)
    {
        scanf("%s%s",str1,str2);
        p=str1;
        x=dfs(0);
        p=str2;
        y=dfs(0);
        if(x==y)printf("same\n");
        else printf("different\n");
    }
    return 0;
}
3.正统做法,来自”我爱橙子“的百度空间,运用论文中的方法进行赋hash值,然后对子节点排序,进行异或运算,记得异或是个重复率很小的运算

                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: