poj 1635 树同构 记录成长历程

来源:互联网 发布:cloudtv mac 编辑:程序博客网 时间:2024/05/16 02:04

主要算法来自于杨弋的论文

1,原始暴力代码,直接TLE

#include <iostream>#include <cstdio>#include <cstring>#define LMT 3003using namespace std;//方法有问题,TLEchar 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 3002using 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值,然后对子节点排序,进行异或运算,记得异或是个重复率很小的运算



原创粉丝点击