Description

Input
Output
Sample Input
2 0010011101001011 0100011011001011 0100101100100111 0011000111010101
Sample Output
same different事实上题目意思就是求两个有根树是否同构,这个假设暴力法枚举的话。复杂度是O(N^2)。一中经典的做法是哈希。思想就是使得不同结构的树哈希值不同。而同构的树哈希值同样。
我这个也是參考别人写的。不同的是我先把01串转换为了树状结构表示。然后再递归求哈希值,这样好理解一点。
哈希的策略:先随机产生一系列随机数作为存到数组。接着从根节点出发。递归计算每一个子树的哈希值,将子树的哈希值相加然后和父节点自己相应的数组上的随机数相加得到父节点的哈希值。这个计算结果和子树的顺序是没有关系的,所以同构的树一哈希值一定是一样的。
对于异构的树,必定在某些节点计算的哈希值不同,因为都是随机产生的一些数字,所以他们相加值和另外一棵树哈希值同样的概率也会很低。(应该不能全然保证的,这里我们加了个取模m的操作。依据鸽巢原理,当树的数量超过m,必定有两个树的哈希值是会同样的,但这两个树却未必是同构的,不知道大家认为对不正确?)
import java.util.*;
public class SubwayTreeSstems1635 {
static final int Hn=11000;
static int h[]=new int[Hn];
static Random rand=new Random(System.currentTimeMillis());
static int m=1000000007;
static int index=0;
/**
* @param args
*/
public static void main(String[] args) {
run();
}
private static void init() {
for(int i=0;i<Hn;i++)
h[i]=(rand.nextInt()%m);
}
public static void run()
{
Scanner in=new Scanner(System.in);
int T=in.nextInt();
init();
for(int t=0;t<T;t++)
{
String s1=in.next();
Node tree1=createTree(s1);
String s2=in.next();
Node tree2=createTree(s2);
/*System.out.println(tree1.children.size()+" "+tree2.children.size());
displayTree(tree1);
System.out.println();
displayTree(tree2);*/
int a=hash(tree1,1);
int b=hash(tree2,1);
//System.out.println(a+" "+b);
if(a==b)
{
System.out.println("same");
}
else
{
System.out.println("different");
}
}
}
public static int hash(Node tree,int j)
{
int sum=h[j+5000];//j是树的高度
for(Node n:tree.children)
sum=(sum+h[j]*hash(n,j+1))%m;//把子树的哈希值加到父节点上去
return (sum*sum)%m;
}
private static Node createTree(String s) {
char[] seq=s.toCharArray();
Node root=new Node(0);
Node p=root;
int index=1;
for(int i=0;i<seq.length;i++)
{
if(seq[i]==‘0‘)
{
Node node =new Node(index++);
connect(p,node);
p=node;
}
else if(seq[i]==‘1‘)
{
p=p.parent;
}
}
//if(p==root)
// System.out.println("create success!");
return root;
}
private static void connect(Node p, Node node) {
node.parent=p;
p.children.add(node);
}
public static void displayTree(Node tree)
{
System.out.println(tree);
for(Node ch:tree.children)
displayTree(ch);
}
}
class Node
{
int id;
Node parent=null;
List<Node> children=new ArrayList<Node>();
public Node(int n)
{
id=n;
}
public String toString()
{
StringBuilder sb=new StringBuilder();
sb.append(id).append(": ");
for(Node n:children)
sb.append(n.id).append(" ");
return sb.toString();
}
}
poj-1635 Subway tree systems(推断两个有根树是否同构)-哈希法
原文:http://www.cnblogs.com/lytwajue/p/6917476.html