在人民银行那里,每个银行的每一个营业网点都有自己唯一的银行联行号,根据这个号码能快速定位一间银行具体的分支行,就像根据一个身份证号码能快速确定一个人一样。例如汇款时,汇款单上要求填写收款人开户行,然后银行会把收款人开户行的联行号连其他信息发到人民银行进行清算,这样能保证以最快的速度汇到收款人的手上。如果联行号不准确,那么在汇款的时候会发生分行落地,支行间调拨等操作,影响导致时间,尤其是跨行汇款的时候。一般银行的代收付接口,都会要求提供此参数。

银行联行号一般是根据输入的分支行信息模糊查询出来的,有的银行接口也会提供类似的根据传入的信息返回联行号的接口,其实现的技术也是根据模糊匹配思路,只是不同的银行实现的水准高低不同,如输入"工行海淀支行"有的返回的是中国工商银行北京市分行海淀镇支行营业室102100000458,有的返回的是中国工商银行北京市海淀支行四季青分理处102100024537。

本文主要是基于前两年在支付行业的代码实战,通过联行号模糊查询示例讲解KMP与Levenshtein模糊匹配算法,有关此两种算法的介绍可以参考Levenshtein字符串距离算法介绍KMP字符串匹配算法,本文只是整个查询功能的代码示例,为了专注算法重点,略去了银行同义词之间的匹配与模糊地市查询能力。(银行同义词如工行、工商银行、中国工商银行股份有限公司,模糊地市如江西省南昌市、江西南昌)

先看整体效果

主要代码说明:

  1. swing初始化及数据加载

     1 try {
    2 JFrame frame = new JFrame("银行模糊匹配---edited by Dimmacro");
    3 textLabel = new JLabel("请输入待匹配的字符串:");
    4 textLabel.setFont(new Font("Default", Font.PLAIN, 18));
    5 textField = new JTextField(30);
    6 textField.setFont(new Font("Default", Font.PLAIN, 18));
    7 resultArea = new JTextArea();
    8 resultArea.setFont(new Font("Default", Font.BOLD, 15));
    9 resultArea.setEditable(false);
    10 // 设置窗口初始化大小为屏幕大小的1/4,位置在最中间
    11 JPanel panel = new JPanel();
    12 panel.add(textLabel);
    13 panel.add(textField);
    14 frame.getContentPane().add(panel, BorderLayout.NORTH);
    15 frame.getContentPane().add(new JScrollPane(resultArea), BorderLayout.CENTER);
    16
    17 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    18 Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
    19 frame.setSize(d.width / 2, d.height / 2);
    20 frame.setLocation((d.width - frame.getSize().width) / 2, (d.height - frame.getSize().height) / 2);
    21 frame.setVisible(true);
    22 textField.addKeyListener(new KeyAdapter() {
    23 public void keyReleased(KeyEvent e) {
    24 startTime = System.nanoTime();
    25 readyCheck = true;
    26 }
    27
    28 public void keyPressed(KeyEvent e) {
    29 startTime = System.nanoTime();
    30 readyCheck = false;
    31 }
    32
    33 });
    34 } catch (Exception e) {
    35 e.printStackTrace();
    36 resultArea.setText("执行出错!");
    37 }
  2. 联行号数据加载:需要把联行号数据库先加载到内存中,其单行格式为:102100000030,中国工商银行北京市分行营业部
     1 private static long initSourceData() {
    2 long counts = 0;
    3 try {
    4 InputStream bankCodeInputStream = BankMatch.class.getClassLoader().getResourceAsStream(bankCodeFile);
    5 BufferedReader bReader = new BufferedReader(new InputStreamReader(bankCodeInputStream, "GBK"),20480);
    6 String lineString;
    7 bankMap = new HashMap<String, String>();
    8 String code, name;
    9 while ((lineString = bReader.readLine()) != null) {
    10 int firstCommaIndex = lineString.indexOf(",");
    11 code = lineString.substring(0, firstCommaIndex);
    12 name = lineString.substring(firstCommaIndex + 1);
    13 // System.out.println("code=" + code + " and name=" + name+"=========="+counts);
    14 bankMap.put(code, name);
    15 counts++;
    16 }
    17 } catch (Exception e) {
    18 e.printStackTrace();
    19 }
    20 return counts;
    21 }
  3. 根据传入的参数模糊查询,返回符合条件的列表,并按最佳匹配程度进行排序
     1     public List<String> handleMatch() {
    2 List<String> resultList = new ArrayList<String>();
    3 String code, name;
    4 String[] nameArray;
    5 String findResult;
    6 for (Map.Entry<String, String> entry : bankMap.entrySet()) {
    7 code = entry.getKey();
    8 name = entry.getValue();
    9 nameArray = name.split(",");
    10 findResult = code + "," + nameArray[0];
    11 List<String> arrangeList = new ArrayList<String>();
    12 resultStr = new String[nameArray.length];
    13 arrageArray(arrangeList, nameArray); // 如果有省份城市,重排其顺序以保证匹配的准确性
    14 for (String oneArrangeStr : arrangeList) {
    15 name = oneArrangeStr.replaceAll(",", "");
    16 // 处理BMP全字匹配的情况
    17 if ((KMPMatchString.kmpMatch(name, matchStr) || KMPMatchString.kmpMatch(matchStr, name)) && !resultList.contains(findResult)) {
    18 resultList.add(findResult);
    19 match.printOut(findResult);
    20 match.getShowArea().selectAll();
    21 }
    22 }
    23 }
    24 // Levenshtein 模糊算法
    25 if (resultList.size() > 0) {
    26 // 根据Levenshtein 模糊算法排序
    27 Collections.sort(resultList, new Comparator<String>() {
    28 public int compare(String s1, String s2) {
    29 return LevenshteinMacthString.levenshteinMacth(s1.split(",")[1], matchStr)
    30 - LevenshteinMacthString.levenshteinMacth(s2.split(",")[1], matchStr);
    31 }
    32 });
    33 }
    34 return resultList;
    35 }
  4. KMP算法
     1 public static boolean kmpMatch(String source, String target)
    2 {
    3 if(null == source || null == target || "".equals(source.trim()) || "".equals(target.trim()))
    4 {
    5 return false;
    6 }
    7
    8 int bl = source.length();
    9 int al = target.length();
    10
    11 for(int bi = 0,ai = 0;bi < al;ai++)
    12 {
    13 if(bi == al || ai == bl)
    14 {
    15 return false;
    16 }
    17 else if(source.charAt(ai) == target.charAt(bi))
    18 {
    19 bi++;
    20 }
    21 }
    22 return true;
    23 }
  5. Levenshtein算法
     1 public static int levenshteinMacth(String source,String target) {
    2 int n = target.length();
    3 int m = source.length();
    4 int[][] d = new int[n + 1][m + 1];
    5
    6 // Step 1
    7 if (n == 0) {
    8 return m;
    9 }
    10
    11 if (m == 0) {
    12 return n;
    13 }
    14
    15 // Step 2
    16 for (int i = 0; i <= n; d[i][0] = i++) {
    17 }
    18
    19 for (int j = 0; j <= m; d[0][j] = j++) {
    20 }
    21
    22 // Step 3
    23 for (int i = 1; i <= n; i++) {
    24 // Step 4
    25 for (int j = 1; j <= m; j++) {
    26 // Step 5
    27 // System.out.println(t.charAt(j - 1));
    28 // System.out.println(s.charAt(i - 1));
    29 // int cost = (t.charAt(j - 1) == s.charAt(i - 1)) ? 0 : 1;
    30 int cost = (source.substring(j - 1, j) == target.substring(i - 1, i) ? 0 : 1);
    31
    32 // Step 6
    33 d[i][j] = Math.min(Math.min(d[i - 1][j] + 1, d[i][j - 1] + 1), d[i - 1][j - 1] + cost);
    34 }
    35 }
    36 // Step 7
    37 return d[n][m];
    38 }
  6. 附件下载:Eclipse工程,直接导入运行BankMatch类即可看到效果。下载
  7. 遗留代码问题:如整体效果看到的那样,每次从输入框输入完释放最后一次按键时,如果1秒内没有接着按下一个键,才会开始查询,这样既可以做到根据输入的效果实时查询,又不至于要每次输入一个字符就开始查。对于这个实现采用的是wihe(true)的方式,但是发现如果不加线程sleep的话会出现不响应查询的情况,请万能的博客园高手看看。

http://www.cnblogs.com/dimmacro/p/4482903.html

基于KMP与Levenshtein模糊匹配算法的银行联行号查询(转)的更多相关文章

  1. 基于KMP与Levenshtein模糊匹配算法的银行联行号查询

    在人民银行那里,每个银行的每一个营业网点都有自己唯一的银行联行号,根据这个号码能快速定位一间银行具体的分支行,就像根据一个身份证号码能快速确定一个人一样.例如汇款时,汇款单上要求填写收款人开户行,然后 ...

  2. 求最长公共前缀和后缀—基于KMP的next数组

    KMP算法最主要的就是计算next[]算法,但是我们知道next[]求的是当前字符串之前的子字符串的最大前后缀数,但是有的时候我们需要比较字符串中前后缀最大数,比如 LeetCode的shortest ...

  3. 基于KMP算法的字符串模式匹配问题

    基于KMP算法的字符匹配问题 反正整个清明都在纠结这玩意...差点我以为下个清明要给自己过了. 至于大体的理解,我就不再多说了(还要画图多麻烦鸭),我参考了以下两个博客,写的真的不错,我放了超链接,点 ...

  4. C#:根据银行卡卡号判断银行名称

    原文地址:android 根据银行卡卡号判断银行 原文是 java ,现在将它翻译成 C# ,并对代码重新编排整理,博主是一个今年刚出来的应届毕业生,不足之处请多多包涵. 根据银行卡号判断所属银行,依 ...

  5. 国内银行CNAPS CODE 查询

    原地址:http://weekend.blog.163.com/blog/static/746895820127961346724/ 全国各地,无论哪个银行,无论什么分行,所有的CNAPS CODE都 ...

  6. C#:根据银行卡卡号推断银行名称

    原文:C#:根据银行卡卡号推断银行名称 原文地址:android 根据银行卡卡号判断银行 原文是 java ,现在将它翻译成 C# ,并对代码重新编排整理,不足之处请多多包涵. 根据银行卡号判断所属银 ...

  7. C#_根据银行卡卡号判断银行名称

    /// <summary> /// 银行信息 /// </summary> public class BankInfo { #region 数组形式存储银行BIN号 /// & ...

  8. 前端JS校验银行卡卡号和身份证号码(附ES6版方法)

    1.银行卡卡号校验方法. function luhnCheck(bankno) { var lastNum = bankno.substr(bankno.length - 1, 1); //取出最后一 ...

  9. 华为OJ训练之 简易的银行排号叫号系统

    闯关第五关的题目,一个中级题和一个高级题.中间题比較简单,半个小时完毕了.题目例如以下 实现一个简易的银行排号叫号系统 get    取号                     演示样例:" ...

随机推荐

  1. JAVA的反射机制学习笔记(二)

    上次写JAVA的反射机制学习笔记(一)的时候,还是7月22号,这些天就瞎忙活了.自己的步伐全然被打乱了~不能继续被动下去.得又一次找到自己的节奏. 4.获取类的Constructor 通过反射机制得到 ...

  2. openCV之头文件分析

    我们利用openCV开源库进行项目开发时,往往要牵涉到头文件的添加问题,而openCV中头文件众多,该如何选择呢?下面对openCV2.4.10的头文件进行一个简单的梳理,以便能够快速的添加对应的头文 ...

  3. 如何在Android Studio上使用Github

    首先,登陆到Github上并创建一个新repository.在屏幕右上角,点击“+”标记,并且选择“New repository”. 现在完成这个表格以新建一个叫做testproject的新repos ...

  4. 后缀数组--可重叠的K次最长重复子串(POJ3261)

    题目:Milk Patterns #include <stdio.h> #include <string.h> #define N 1000010 int wa[N],wb[N ...

  5. http staus汇总

    参考http://www.cnblogs.com/cxd4321/archive/2008/11/20/1337776.html 常见HTTP状态码 200 OK 301 Moved Permanen ...

  6. Kaggle—Digit Recognizer竞赛

    Digit Recognizer 手写体数字识别  MNIST数据集 本赛 train 42000样例 test 28000样例,原始MNIST是 train 60000 test 10000 我分别 ...

  7. windows 7多点触摸开发

    win7 触摸屏系统应用广泛,软件操作方便,功能强大,现以被很多硬件厂商应用. 我曾用一台装有win7 的汉王平板电脑进行了多点触摸软件的开发.      开发环境及条件: 1. 平板电脑+ win7 ...

  8. Ubuntu 12.04更新源

    源地址:http://www.cnblogs.com/eastson/archive/2012/08/24/2654163.html 1.首先备份Ubuntu12.04源列表 sudo cp /etc ...

  9. GIS Tools for Hadoop 详细介绍

    2013年Esri美国在开发者大会上演示了GIS数据结合Hadoop分析的一个示例,这个示例赢得了听众的阵阵掌声,我们也许对GIS不是很陌生,但是对Hadoop却不是很清楚,其实Esri是用Java开 ...

  10. 我的EJB学习历程

    http://blog.csdn.net/sinapaper/archive/2004/06/28/28659.aspx http://blog.csdn.net/sinapaper/archive/ ...