zoukankan      html  css  js  c++  java
  • SDUT3926 kmp

    bLue的二叉树

    Time Limit: 3000MS Memory Limit: 65536KB

    Problem Description

    Keke 是一个喜爱种树的人,他对各种树都有很深的研究。

    MLE 听说 bLue 种了一些新品种的树,就想邀请 Keke 去围观一下。

    PBH 在暗中把这一切尽收眼底,作为资深植树行家,他虽不屑,但也决定和他们一起去看一看。

    于是,大家便一起到了 bLue 家去看树。

    bLue 有两棵二叉树,分别有 n 和 m 个节点,编号分别为 1-n 和 1-m,每个节点都有一个权值,bLue 想知道第一棵树的所有子树中与第二棵树完全相同的个数(不考虑节点编号)。

    Input

    输入数据有多组(数据组数不超过 150),到 EOF 结束。

    对于每组数据:

    • 第一行有两个整数 n (0 < n <= 10^5) 和 m (0 < m <= 10^5),表示第一棵树和第二棵树的节点个数
    • 接下来 n 行,表示第一棵树:第 i (0 < i <= n) 行有 3 个整数,w[i] (0 < w[i] <= 10), lc[i], rc[i] (0 < lc[i], rc[i] <= n),分别表示节点 i 的权值,该节点的左孩子编号和右孩子编号,若某个孩子不存在,则为 0 (数据保证每棵树都是合法的有根二叉树)
    • 接下来 m 行,表示第二棵树:格式同第一棵树

    保证:树的最大深度不会超过 10000。

    Output

    对于每组数据,输出一行一个整数 num,表示第一棵树的所有子树中与第二棵树完全相同的个数。

    Example Input

    7 4
    1 6 3
    2 0 4
    1 7 0
    3 0 0
    1 2 1
    2 0 0
    2 0 0
    2 0 0
    1 4 0
    1 1 2
    2 0 0
    3 3
    1 0 0
    2 1 3
    3 0 0
    1 0 3
    2 1 0
    3 0 0

    Example Output

    1
    0

    Hint

    数据量比较大,推荐用 scanf 等读入。

    题意:

    有两颗二叉树分别有n个和m个顶点,求前一棵树中有多少子树与后一棵树完全相同(不考虑节点编号)

    输入n m

    输入n行a b c表示该号节点权值为a,左右儿子分别是b和c(0表示不存在该儿子)

    输入m行

    代码:

    //想不到可以kmp,将两棵树的前序遍历写出来(节点权值),不存在的节点要补0,然后将得到的两个串
    //进行kmp找后一个串在前一个串中出现了多少次。
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int MAXN=400009;
    struct Node{
        int l,r,w;
    }node[2][MAXN];
    int N,M,cnt,len1,len2;
    int ch[2][MAXN];
    bool vis[MAXN];
    int f[MAXN],f2[MAXN];
    void dfs(int id,int rt){
        ch[id][cnt++]=node[id][rt].w;
        if(node[id][rt].l!=0){
            dfs(id,node[id][rt].l);
        }else{
            ch[id][cnt++]=0;
        }
        if(node[id][rt].r!=0){
            dfs(id,node[id][rt].r);
        }else{
            ch[id][cnt++]=0;
        }
    }
    void getfail(int* P,int* f){
        f[0]=0;f[1]=0;
        f2[0]=0;f2[1]=0;
        for(int i=1;i<len2;i++){
            int j=f2[i];
            while(j&&P[i]!=P[j]) j=f2[j];
            f2[i+1]=f[i+1]=(P[i]==P[j]?j+1:0);
            if(f[i+1]==j+1&&P[i+1]==P[j+1]) f[i+1]=f[j+1];
        }
    }
    int find(int* T,int* P,int* f){
        getfail(P,f);
        int j=0,ans=0;
        for(int i=0;i<len1;i++){
            while(j&&P[j]!=T[i]) j=f[j];
            if(P[j]==T[i]) j++;
            if(j==len2) ans++;
        }
        return ans;
    }
    int main()
    {
        while(scanf("%d%d",&N,&M)==2){
            int a,b,c,rt1,rt2;
            memset(vis,0,sizeof(vis));
            for(int i=1;i<=N;i++){
                scanf("%d%d%d",&a,&b,&c);
                node[0][i].w=a;
                node[0][i].l=b;
                node[0][i].r=c;
                vis[b]=vis[c]=1;
            }
            for(int i=1;i<=N;i++)if(!vis[i]){
                rt1=i;break;
            }
            memset(vis,0,sizeof(vis));
            for(int i=1;i<=M;i++){
                scanf("%d%d%d",&a,&b,&c);
                node[1][i].w=a;
                node[1][i].l=b;
                node[1][i].r=c;
                vis[b]=vis[c]=1;
            }
            for(int i=1;i<=M;i++)if(!vis[i]){
                rt2=i;break;
            }
            cnt=0;
            dfs(0,rt1);
            len1=cnt;
            cnt=0;
            dfs(1,rt2);
            len2=cnt;
            int ans=find(ch[0],ch[1],f);
            printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    tomact配置
    cesium环境配置
    电脑上压缩文件不显示图标的解决办法
    MSCE C#官网一步步学习搬运9 第九章、用C++/CLI编写Addins
    MSCE | MDL二次开发知识点与遇到的问题记录
    MSCE C++官网一步步学习搬运7
    MSCE C++官网一步步学习搬运6
    geotools模块梳理
    geoserver 安全配置
    mapbox去除logo控件和attribution控件
  • 原文地址:https://www.cnblogs.com/--ZHIYUAN/p/6953796.html
Copyright © 2011-2022 走看看