树A与树B的同构问题(可以转换为字符串问题)

对于两棵彼此独立的二叉树A和B,请编写一个高效算法,检查A中是否存在一棵子树与B树的拓扑结构完全相同。
给定两棵二叉树的头结点A和B,请返回一个bool值,代表A中是否存在一棵同构于B的子树。

注意事项
1、把书字符串化(前序、中序、后序)
2、第一种方法:直接配对(时间复杂度O(M*N))
第二种方法:KMP算法,时间复杂度O(M+N)
1、string A,B,C ,if(C.find(B)!=string::npos)说明C中有B
第二种方法:KMP
next函数:

void cal_next(char *str, int *next, int len)
{
    next[0] = -1;//next[0]初始化为-1,-1表示不存在相同的最大前缀和最大后缀
    int k = -1;//k初始化为-1
    for (int q = 1; q <= len-1; q++)
    {
        while (k > -1 && str[k + 1] != str[q])//如果下一个不同,那么k就变成next[k],注意next[k]是小于k的,无论k取任何值。
        {
            k = next[k];//往前回溯
        }
        if (str[k + 1] == str[q])//如果相同,k++
        {
            k = k + 1;
        }
        next[q] = k;//这个是把算的k的值(就是相同的最大前缀和最大后缀长)赋给next[q]
    }
}

KMP函数

int KMP(char *str, int slen, char *ptr, int plen)
{
    int *next = new int[plen];
    cal_next(ptr, next, plen);//计算next数组
    int k = -1;
    for (int i = 0; i < slen; i++)
    {
        while (k >-1&& ptr[k + 1] != str[i])//ptr和str不匹配,且k>-1(表示ptr和str有部分匹配)
            k = next[k];//往前回溯
        if (ptr[k + 1] == str[i])
            k = k + 1;
        if (k == plen-1)//说明k移动到ptr的最末端
        {
            //cout << "在位置" << i-plen+1<< endl;
            //k = -1;//重新初始化,寻找下一个
            //i = i - plen + 2;//i定位到找到位置处的下一个位置(这里默认存在两个匹配字符串可以部分重叠)
            return i-plen+1;//返回相应的位置
        }
    }
    return -1;  
}

代码实现:

/*
struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
    TreeNode(int x) :
            val(x), left(NULL), right(NULL) {
    }
};*/
class IdenticalTree {
public:
    bool chkIdentical(TreeNode* A, TreeNode* B) {
        // write code here
        string A_str{};
        string B_str{};
        treetostring(A,A_str);
        treetostring(B,B_str);
        int k=kmp(A_str,B_str);
        if(k==-1)
            return false;
        else
            return true;
    }

    void treetostring(TreeNode* root,string &s)
        {
        if(root==NULL)
        {
            s+="#!";
            return;
        }
        s+=to_string(root->val);
        s+="#";
        treetostring(root->left,s);
        treetostring(root->right,s);
    }

   int kmp(string &A,string &B)
       {
       int slen=A.length();
       int plen=B.length();
       int *next=new int[plen];
       cal_next(B,next,plen);
       int k=-1;
       for(int i=0;i<slen;i++)
           {
           while(k>-1&&B[k+1]!=A[i])
               k=next[k];
           if(B[k+1]==A[i])
               k=k+1;
           if(k==plen-1)
               return i-plen+1;

       }
       return -1;
   }
    void cal_next(string &A,int* next,int len)
        {
        next[0]=-1;
        int k=-1;
        for(int q=1;q<len-1;q++)
            {
            while(k>-1&&A[k+1]!=A[q])
                {
                k=next[k];
            }
            if(A[k+1]==A[q])
                {
                k=k+1;
            }
            next[q]=k;
        }
    }
};

你可能感兴趣的:(数据结构与算法)