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(); } }