1. 递归的方式
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};*/
class Solution {
public:
bool HasSubtree(TreeNode* pRoot1, TreeNode* pRoot2)
{
//递归的实现方式
bool result=false;
if(pRoot1==NULL||pRoot2==NULL)
return false;
if(pRoot1->val==pRoot2->val)
result=getResult(pRoot1,pRoot2);//这里的递归是进入下面的函数!!!
if(result==false)
result=HasSubtree(pRoot1->left,pRoot2);//这里的递归是递归自己!!!
if(result==false)
result=HasSubtree(pRoot1->right,pRoot2);//这里的递归是递归自己!!!
return result;
}
bool getResult(TreeNode* p1,TreeNode* p2){
if(p1==NULL&&p2==NULL)
return true;
if(p1==NULL&&p2!=NULL)
return false;
if(p1!=NULL&&p2==NULL)
return true;
if(p1->val==p2->val)
return getResult(p1->left,p2->left)&&getResult(p1->right,p2->right);
else
return false;
}
};
递归的过程如上面所示,需要注意的是这是两个不同的递归过程!!!!
2. 序列化然后利用KMP算法进行模式串的匹配
KMP算法的时间复杂度为O(m+n),可以用均摊分析来证明。具体的证明可以查看http://www.matrix67.com/blog/archives/115。
普通的模式串匹配算法的时间复杂度为o(m*n)
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};*/
class Solution {
public:
bool HasSubtree(TreeNode* pRoot1, TreeNode* pRoot2)
{
if(pRoot1==NULL||pRoot2==NULL)
return false;
//先将两棵树进行序列化,然后进行模式串匹配!!!
string s1,s2;
getResult(pRoot1,s1);
getResult(pRoot2,s2);
//下面是KMP
return getkmp(s1,s2);
}
void getResult(TreeNode* r,string& s){
//采用先序遍历的过程,需要注意的是这里不需要#,只需要!!!!原因是如果带有#,那么对于s2来说,s1中包含的s2也许他的孩子并不是空,但是s2中叶节点的孩子
//为空,这样会导致结果的错误!!!因为生成的字符串必然是不相等的,所以不需要#。
if(r!=NULL)
s=s+to_string(r->val)+"!";
else{
return;
}
getResult(r->left,s);
getResult(r->right,s);
return;
}
bool getkmp(string s1,string s2){
int* next=getnext(s2);
int j = 0;
int size=s1.length();
int size2=s2.length();
for (int i = 0; i < size; i++) {
while (j > 0 && s1[i] !=s2[j])
j = next[j];
if (s1[i] ==s2[j])
j++;
if (j == size2) {
return true;
}
}
return false;
}
//求s1的next数组
int* getnext(string b){
int len=b.length();
int j=0;
int* next=new int[len+1];//next表示长度为i的字符串前缀和后缀的最长公共部分,从1开始
next[0]=next[1]=0;
for(int i=1;i<len;i++)//i表示字符串的下标,从0开始
{//j在每次循环开始都表示next[i]的值,同时也表示需要比较的下一个位置
while(j>0&&b[i]!=b[j])j=next[j];
if(b[i]==b[j])j++;
next[i+1]=j;
}
return next;
}
};
字符串匹配算法除了KMP之外还有BM等。