日期:2014-05-20  浏览次数:20733 次

求一算法
源数据
A: 0、1
B: 0、1、2
C: 0、1、2、3
由ABC三组数据组合成(每组数据取其中1位,由A到C开始组合)

需求:
源数据 通过算法,找出与之匹配的目标数据(目标数据同源数据组合规律一致)
匹配规则:
1、源数据中的第A位数,目标数据中必须也有第A位数据;要匹配的数据为1
2、源数据中的第B位数,目标数据中必须也有第B位数据;要匹配的数据为0和1
3、源数据中的第C位数,目标数据中必须也有第C位数据;要匹配的数据为0和1

例:(源数据可以有剩余,但目标数据必须源数据由源数据全部匹配;前提:源数据一定会找出匹配目标数据的,这点不用考虑)
源数据为
100、101、101、011、002、020、023、123
目标数据为
100、101、003、012、020、121

得到的结果为
100 匹配100
101 匹配101
002 匹配003
001 匹配012
020 匹配020

想了两天了,也没想出来,望大能指导一二,先行谢谢了……



------解决方案--------------------
Java code

import java.util.*;
public class Test {
    public static void main(String[] args) throws Throwable {
        String[] a = {"0", "1"};
        String[] b = {"0", "1", "2"};
        String[] c = {"0", "1", "2", "3"};
        String[][] src = new String[][]{a, b, c};

        Map<String, List<String>> map = getRules(src);
        List<Map.Entry<String, List<String>>> rules = new ArrayList<Map.Entry<String, List<String>>>(map.entrySet());
        Collections.sort(rules, new Comparator<Map.Entry<String, List<String>>>() {
            public int compare(Map.Entry<String, List<String>> r1, Map.Entry<String, List<String>> r2) {
                return r2.getKey().compareTo(r1.getKey());
            }
        }); //按111(符合规则123),110(符合规则12),...000(不符合规则)的顺序,把符合规则的组合排序

        String[] srcData = {"100", "101", "101", "011", "002", "020", "023", "123"};
        String[] tagData = {"100", "101", "003", "012", "020", "121"};

        List<String> srcList = new ArrayList<String>(Arrays.asList(srcData));
        boolean match = false;
        List<String> rule = null;
        String key = null;
        int min = 7, last = -1;
Outer:  for (String s : tagData) {
            min = 7;
            last = -1;
            for (int i=0; i<rules.size()-1; i++) {
                rule = rules.get(i).getValue();
                key = rules.get(i).getKey();
                if (rule.contains(s)) {
                    for (int j=0; j<srcList.size(); j++) {
                        String ss = srcList.get(j);
                        if (rule.contains(ss)) {
                            match = true;
                            for (int k=0; k<i; k++) {
                                if (rules.get(k).getValue().contains(ss)) {
                                    match = false;
                                    if (i-k < min) { //规则不完全相同,则匹配规则最接近的
                                        min = i-k;
                                        last = j;
                                    }
                                    break;
                                }
                            }
                            if (match) {
                                for (int k=0; k<key.length(); k++) {
                                    if (key.charAt(k) == '1') {
                                        match &= (s.charAt(k) == ss.charAt(k));
                                    }
                                } 
                            }
                            if (match) { //规则完全相同的匹配
                                System.out.printf("%s:%s\n", ss, s);
                                srcList.add(srcList.remove(j));
                                continue Outer;
                            } else {
                                if (last == -1) last = j;
                            }
                        }
                    }                    
                }
            }
            if (last != -1) {
                System.out.printf("%s:%s\n", srcList.get(last), s);
                srcList.add(srcList.remove(last));
            }
        }
    }

    public static Map<String, List<String>> getRules(String[][] src) {
        String[] rule = {"1", "01", "01"};
        int[] dig = new int[src.length];
        int[] bit = new int[rule.length];
        StringBuilder buf = new StringBuilder();
        StringBuilder key = new StringBuilder();
        Map<String, List<String>> map = new HashMap<String, List<String>>();
        for (int i=0; i<8; i++) {
            buf.delete(0, buf.length());
            buf.append("000").append(Integer.toBinaryString(i));
            map.put(buf.substring(buf.length()-3), new ArrayList<String>());
        }
        while (dig[0] < src[0].length) {
            buf.delete(0, buf.length());
            for (int i=0; i<src.length; i++) { 
                buf.append(src[i][dig[i]]); 
            }

            for (int i=0, b=i; i<8; i++, b=i) {
                key.delete(0, key.length());
                boolean match = true;
                for (int j=bit.length-1; j>=0; j--) {
                    bit[j] = b%2;
                    b >>= 1;
                    key.insert(0, bit[j]);
                    
                    if (bit[j] == 1) {
                        match &= rule[j].contains(src[j][dig[j]]);
                    }
                }
                if (match) {
                    map.get(key.toString()).add(buf.toString());
                }                
            }

            dig[dig.length-1]++;
            for (int i=dig.length-1; i>0; i--) {
                if (dig[i] == src[i].length) {
                    dig[i] = 0;
                    dig[i-1]++;
                } else {
                    break;
                }
            }            
        }

        return map;
    }
}