ZJU 1990 Subway tree systems - 树的最小表示

题目大意:

初始时站在树的根节点,若朝着远离根的方向走,记录“0”,接近根的方向走记录“1”。并且树的每一条边只能来回走一次(即向下和返回)。一个合法的01序列可以描述出一棵树的形态。现在给出两个合法的01序列,判断两棵树是否同构。

分析:

由于根节点确定,若两棵树同构,无非就是把子树的位置交换了一下。很自然的想法就是:将树的子树按照某种规则进行排序,若排序之后两个字符串相等,则同构;否则不同构。

现在来分析一下01序列,可以看出,当一个串的“0”和“1”个数相等时,恰好就是一棵子树。例如:

0010011101001011

可以划分为一下三棵子树

00100111,01,001011

而对于每部分划分来说,去掉第一个0和末尾的1,得到的就遍历是这棵子树的01序列(空串表示子树为空)。这样便出现了递归结构

将这棵树最小表示的算法描述如下:

0、若01序列为空,返回。

1、划分出该01序列的每一棵子树。

2、对于每棵子树,去掉第一个0和末尾1之后,递归进行最小表示。

3、得到每棵子树的最小表示后,将子树的01串按照strcmp排序。

 

  1. /*
  2. ZJU1990 Subway tree systems
  3. */
  4. #include <stdio.h>
  5. #include <string.h>
  6. #include <stdlib.h>
  7. #define N 3005
  8. typedef struct{
  9.     int f,len;
  10. }Node;
  11. Node bm[N/2][N/2];
  12. int nbm;
  13. char temp[N],*sp;
  14. int cmp(const void *A,const void *B){
  15.     Node a = *((Node*)A);
  16.     Node b = *((Node*)B);
  17.     int i,m=(a.len>b.len?b.len:a.len);
  18.     for(i=0;i<m;i++){
  19.         if(sp[a.f+i]!=sp[b.f+i])
  20.             return sp[a.f+i] - sp[b.f+i];
  21.     }
  22.     return 0;
  23. }
  24. void MinRep(char s[],int n){
  25.     int i,j,k,m=0,count=0;
  26.     Node *b=&bm[nbm++][0];
  27.     if(n<=0) return;
  28.     
  29.     for(i=0;i<n;i++){
  30.         if(count==0) b[m].f=i;
  31.         if(s[i]=='0') count++;
  32.         else count--;
  33.         if(count==0) {
  34.             b[m].len=i-b[m].f+1;
  35.             m++;
  36.         }
  37.     }
  38.     
  39.     for(k=0;k<m;k++) Min(s+b[k].f+1,b[k].len-2);
  40.     
  41.     sp=s;
  42.     qsort(b,m,sizeof(Node),cmp);
  43.     
  44.     for(i=k=0;k<m;k++){
  45.         for(j=0;j<b[k].len;j++,i++)
  46.             temp[i]=s[b[k].f+j];
  47.     }
  48.     for(i=0;i<n;i++) s[i]=temp[i];
  49.     
  50. }
  51. int main()
  52. {
  53.     int i,j,k,T;
  54.     char s[N];
  55.     char t[N];
  56.     
  57.     scanf("%d",&T);
  58.     while(T--){
  59.         scanf("%s%s",s,t);
  60.         nbm=0;
  61.         MinRep(s,strlen(s));
  62.         nbm=0;
  63.         MinRep(t,strlen(t));
  64.         if(strcmp(s,t)==0) puts("same");
  65.         else puts("different");
  66.     }
  67.     
  68.     return 0;
  69. }
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值