哈希法判断两个有根树是否同构

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串转换为了树状结构表示,然后再递归求哈希值,这样好理解一点。

更多精彩内容:http://www.bianceng.cnhttp://www.bianceng.cn/Programming/sjjg/

哈希的策略:先随机产生一系列随机数作为存到数组,接着从根节点出发,递归计算每个子树的哈希值,将子树的哈希值相加然后和父节点自己对应的数组上的随机数相加得到父节点的哈希值。这个计算结果和子树的顺序是没有关系的,所以同构的树一哈希值一定是一样的。对于异构的树,必然在某些节点计算的哈希值不同,由于都是随机产生的一些数字,所以他们相加值和另外一棵树哈希值相同的概率也会非常低。(应该不能完全保证的,这里我们加了个取模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();
    }
}

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索static
, 节点
, 哈希
, of
, The
, You
, 再哈希法
两个值相加
如何判断同构图、判断两个图是否同构、如何判断两个图同构、怎么判断两个图同构、同构图形,以便于您获取更多的相关知识。

时间: 2024-09-09 17:13:43

哈希法判断两个有根树是否同构的相关文章

源码:判断两种颜色值是否为相似颜色

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" lang="gb2312"> <head> <head&g

Delphi中判断两个时间差是否在一个指定范围内

WithinPastYears.WithinPastMonths.WithinPastWeeks.WithinPastDays ... 判断两个时间差是否在一个指定范围内 DateUtils.WithinPastYears(); DateUtils.WithinPastMonths(); DateUtils.WithinPastWeeks(); DateUtils.WithinPastDays(); DateUtils.WithinPastHours(); DateUtils.WithinPas

php判断两个日期之间相差多少个月份的方法

  本文实例讲述了php判断两个日期之间相差多少个月份的方法.分享给大家供大家参考.具体实现方法如下: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 /** * @author injection(injection.mail@gmail.com) * @var date1日期1 * @var date2 日期2 * @var tags 年月日之间的分隔符标记,默认为'-' * @return 相差的月份数量 * @example: $date1 = "

C# 判断两张图片是否一致的快速方法

 这篇文章主要介绍了C# 判断两张图片是否一致的快速方法,需要的朋友可以参考下 代码如下: #region 判断图片是否一致  /// <summary>  /// 判断图片是否一致  /// </summary>  /// <param name="img">图片一</param>  /// <param name="bmp">图片二</param>  /// <returns>是

php判断两个浮点数是否相等的方法

 本文实例讲述了php判断两个浮点数是否相等的方法.分享给大家供大家参考.具体分析如下: 由于浮点数直接用==判断是否相等是不完全正确的,所以下面给出了一个方法,先设定的一个精度,如果在精度范围内相等则认为相等,否则认为不能 <?php $delta = 0.00001; $a = 1.00000001; $b = 1.00000000; if (abs($a - $b) < $delta) { /* $a and $b are equal */ } ?> 希望本文所述对大家的php程序

JavaScript中判断两个字符串是否相等的方法_基础知识

先将用户的输入值全部转换为大写(或小写),然后再行比较: var name = document.form1.txtUserName.value.toLowerCase(); if(name == "urname") { // statements go here. }       JavaScript有两种相等运算符.一种是完全向后兼容的,标准的"==",如果两个操作数类型不一致,它会在某些时候自动对操作数进行类型转换,考虑下面的赋值语句: var strA =

java爬虫中如何判断两个URL是否属于同一网站

问题描述 java爬虫中如何判断两个URL是否属于同一网站 如何判断两个URL是否属于同一网站,爬虫中要剔除站外链接,应该要怎么做,两个url主域名不一样但属于同一网站,应该通过什么进行判断 解决方案 String url = "http://ask.csdn.net/questions/237143"; Pattern p = Pattern.compile("(?<=http://|\.)[^.]*?\.(com|cn|net|org|biz|info|cc|tv)

编程-Java 三目运算符 判断两个对象是否为空

问题描述 Java 三目运算符 判断两个对象是否为空 //住院非空,对住院进行处理,住院不为空,判断门诊是否为非空,对门诊进行处理 //zyyzjymx!=null?f1(zyyzjymx):mzzdjymx!=null?f1(mzzdjymx):null; 不会写代码... 思路如上 求大神解决~ 解决方案 zyyzjymx!=null?(f1(zyyzjymx)):(mzzdjymx!=null?f1(mzzdjymx):null); 解决方案二: 你的条件写错了吧?住院非空和住院不为空 不

网络-使用ping命令,如何判断两台机器是否在一个子网

问题描述 使用ping命令,如何判断两台机器是否在一个子网 例如:IP为192.168.1.3的主机ping主机IP为192.168.1.4的主机,可通过本机IP以及子网掩码计算出所属子网,那么被ping的主机只有IP,那怎么判断是否一个子网呢?什么协议规范了这个事情?不懂网络,请教下,呵呵~ 解决方案 ping是ICMP协议,在路由协议之下,交换机,hub等会做数据包转发,根据ip地址得到mac来进行数据传输