poj-1635 Subway tree systems(推断两个有根树是否同构)-哈希法

Description

Some major cities have subway systems in the form of a tree, i.e. between any pair of stations, there is one and only one way of going by subway. Moreover, most of these cities have a unique central station. Imagine you are a tourist in one of these cities
and you want to explore all of the subway system. You start at the central station and pick a subway line at random and jump aboard the subway car. Every time you arrive at a station, you pick one of the subway lines you have not yet travelled on. If there
is none left to explore at your current station, you take the subway line back on which you first came to the station, until you eventually have travelled along all of the lines twice,once for each direction. At that point you are back at the central station.
Afterwards, all you remember of the order of your exploration is whether you went further away from the central station or back towards it at any given time, i.e. you could encode your tour as a binary string, where 0 encodes taking a subway line getting you
one station further away from the central station, and 1 encodes getting you one station closer to the central station.

Input

On the first line of input is a single positive integer n, telling the number of test scenarios to follow.Each test scenario consists of two lines, each containing a string of the characters ‘0‘ and ‘1‘ of length at most 3000, both describing a correct exploration
tour of a subway tree system.

Output

exploration tours of the same subway tree system, or the text "different" if the two strings cannot be exploration tours of the same subway tree system.

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();
	}
}
时间: 2024-10-07 05:28:57

poj-1635 Subway tree systems(推断两个有根树是否同构)-哈希法的相关文章

POJ 1635 Subway tree systems Hash法判断有根树是否同构

Hash在信息学竞赛中的一类应用 中的某道例题 "不难想到的算法是使用两个字符串分别表示两棵树,但是如果使用Hash的话应该怎么做呢? 可以使用一种类似树状递推的方法来计算Hash值:  对于一个节点v,先求出它所有儿子节点的Hash值,并从小到大排序,记作H1,H2,„,HD.那么v的Hash值就可以计算为:   (((a * p) ^ H1 mod q) * p ^ H2 mod q).....  换句话说,就是从某个常数开始,每次乘以p,和一个元素异或,再除以q取余,再乘以p,和下一个元素

[有向树的最小表示] poj 1635 Subway tree systems

题目链接: http://poj.org/problem?id=1635 Subway tree systems Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 6541   Accepted: 2747 Description Some major cities have subway systems in the form of a tree, i.e. between any pair of stations, th

poj 1635 Subway tree systems(树的最小表示)

Subway tree systems POJ - 1635 题目大意:给出两串含有‘1’和‘0’的字符串,0表示向下搜索,1表示回溯,这样深搜一颗树,深搜完之后问这两棵树是不是同一棵树 /* 在poj上交需要加一个string头文件,不然会CE 树的最小表示 这里用的最小表示法就是将树的所有子树分别用1个字符串表示,要按字典序排序将他们依依连接起来.连接后如果两个字符串是一模一样的,那么他们必然是同构的.这样原问题就变成了子问题,子树又是一颗新的树. */ #include<iostream>

[ POJ ][ HASH ] 1635 Subway tree systems

首先,对于一个树,我们可以有一种压缩表示: 0010011101001011 其中 0 表示向下走,1 表示向上走.于是: 00100111|01|001011 对于每一段的 0 1 出现次数相同,这种hash方法叫 树的最小表示法 . 1635 题目精简大意:给你n对01字符串,判断每一对儿表示的是不是同一个树,方法: 1.定义 cnt, start, end 来记录当前0 1之和是否相等,start,end 记录相等时所得字数的范围. 2.去首尾得到子串,递归进行1步骤直到子串只为“0 1”

【POJ】【1635】Subway Tree Systems

树的最小表示法 给定两个有根树的dfs序,问这两棵树是否同构 题解:http://blog.sina.com.cn/s/blog_a4c6b95201017tlz.html 题目要求判断两棵树是否是同构的,思路是用树的最小表示法去做.这里用的最小表示法就是将树的所有子树分别用1个字符串表示,要按字典序排序将他们依依连接起来.连接后如果两个字符串是一模一样的,那么他们必然是同构的.这样原问题就变成了子问题,子树又是一颗新的树. 1 Source Code 2 Problem: 1635 User:

POJ1635Subway tree systems

Subway tree systems Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 8049   Accepted: 3357 Description Some major cities have subway systems in the form of a tree, i.e. between any pair of stations, there is one and only one way of going

poj 3321:Apple Tree(树状数组,提高题)

Apple Tree Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 18623   Accepted: 5629 Description There is an apple tree outside of kaka's house. Every autumn, a lot of apples will grow in the tree. Kaka likes apple very much, so he has been

POJ 2367 Genealogical tree 拓扑排序入门

Description The system of Martians' blood relations is confusing enough. Actually, Martians bud when they want and where they want. They gather together in different groups, so that a Martian can have one parent as well as ten. Nobody will be surpris

poj 1635

有根树同构.参考论文<hash在....> 1 #include <iostream> 2 #include <fstream> 3 #include <algorithm> 4 #include <cstring> 5 #include <climits> 6 #include <cmath> 7 8 using namespace std; 9 10 const int leaf_hash=2099; 11 const