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

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

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

先看整体效果

主要代码说明:

  1. swing初始化及数据加载

    1. 1 try {
    2. 2 JFrame frame = new JFrame("银行模糊匹配---edited by Dimmacro");
    3. 3 textLabel = new JLabel("请输入待匹配的字符串:");
    4. 4 textLabel.setFont(new Font("Default", Font.PLAIN, 18));
    5. 5 textField = new JTextField(30);
    6. 6 textField.setFont(new Font("Default", Font.PLAIN, 18));
    7. 7 resultArea = new JTextArea();
    8. 8 resultArea.setFont(new Font("Default", Font.BOLD, 15));
    9. 9 resultArea.setEditable(false);
    10. 10 // 设置窗口初始化大小为屏幕大小的1/4,位置在最中间
    11. 11 JPanel panel = new JPanel();
    12. 12 panel.add(textLabel);
    13. 13 panel.add(textField);
    14. 14 frame.getContentPane().add(panel, BorderLayout.NORTH);
    15. 15 frame.getContentPane().add(new JScrollPane(resultArea), BorderLayout.CENTER);
    16. 16
    17. 17 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    18. 18 Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
    19. 19 frame.setSize(d.width / 2, d.height / 2);
    20. 20 frame.setLocation((d.width - frame.getSize().width) / 2, (d.height - frame.getSize().height) / 2);
    21. 21 frame.setVisible(true);
    22. 22 textField.addKeyListener(new KeyAdapter() {
    23. 23 public void keyReleased(KeyEvent e) {
    24. 24 startTime = System.nanoTime();
    25. 25 readyCheck = true;
    26. 26 }
    27. 27
    28. 28 public void keyPressed(KeyEvent e) {
    29. 29 startTime = System.nanoTime();
    30. 30 readyCheck = false;
    31. 31 }
    32. 32
    33. 33 });
    34. 34 } catch (Exception e) {
    35. 35 e.printStackTrace();
    36. 36 resultArea.setText("执行出错!");
    37. 37 }
  2. 联行号数据加载:需要把联行号数据库先加载到内存中,其单行格式为:102100000030,中国工商银行北京市分行营业部
    1. 1 private static long initSourceData() {
    2. 2 long counts = 0;
    3. 3 try {
    4. 4 InputStream bankCodeInputStream = BankMatch.class.getClassLoader().getResourceAsStream(bankCodeFile);
    5. 5 BufferedReader bReader = new BufferedReader(new InputStreamReader(bankCodeInputStream, "GBK"),20480);
    6. 6 String lineString;
    7. 7 bankMap = new HashMap<String, String>();
    8. 8 String code, name;
    9. 9 while ((lineString = bReader.readLine()) != null) {
    10. 10 int firstCommaIndex = lineString.indexOf(",");
    11. 11 code = lineString.substring(0, firstCommaIndex);
    12. 12 name = lineString.substring(firstCommaIndex + 1);
    13. 13 // System.out.println("code=" + code + " and name=" + name+"=========="+counts);
    14. 14 bankMap.put(code, name);
    15. 15 counts++;
    16. 16 }
    17. 17 } catch (Exception e) {
    18. 18 e.printStackTrace();
    19. 19 }
    20. 20 return counts;
    21. 21 }
  3. 根据传入的参数模糊查询,返回符合条件的列表,并按最佳匹配程度进行排序
    1. 1 public List<String> handleMatch() {
    2. 2 List<String> resultList = new ArrayList<String>();
    3. 3 String code, name;
    4. 4 String[] nameArray;
    5. 5 String findResult;
    6. 6 for (Map.Entry<String, String> entry : bankMap.entrySet()) {
    7. 7 code = entry.getKey();
    8. 8 name = entry.getValue();
    9. 9 nameArray = name.split(",");
    10. 10 findResult = code + "," + nameArray[0];
    11. 11 List<String> arrangeList = new ArrayList<String>();
    12. 12 resultStr = new String[nameArray.length];
    13. 13 arrageArray(arrangeList, nameArray); // 如果有省份城市,重排其顺序以保证匹配的准确性
    14. 14 for (String oneArrangeStr : arrangeList) {
    15. 15 name = oneArrangeStr.replaceAll(",", "");
    16. 16 // 处理BMP全字匹配的情况
    17. 17 if ((KMPMatchString.kmpMatch(name, matchStr) || KMPMatchString.kmpMatch(matchStr, name)) && !resultList.contains(findResult)) {
    18. 18 resultList.add(findResult);
    19. 19 match.printOut(findResult);
    20. 20 match.getShowArea().selectAll();
    21. 21 }
    22. 22 }
    23. 23 }
    24. 24 // Levenshtein 模糊算法
    25. 25 if (resultList.size() > 0) {
    26. 26 // 根据Levenshtein 模糊算法排序
    27. 27 Collections.sort(resultList, new Comparator<String>() {
    28. 28 public int compare(String s1, String s2) {
    29. 29 return LevenshteinMacthString.levenshteinMacth(s1.split(",")[1], matchStr)
    30. 30 - LevenshteinMacthString.levenshteinMacth(s2.split(",")[1], matchStr);
    31. 31 }
    32. 32 });
    33. 33 }
    34. 34 return resultList;
    35. 35 }
  4. KMP算法
    1. 1 public static boolean kmpMatch(String source, String target)
    2. 2 {
    3. 3 if(null == source || null == target || "".equals(source.trim()) || "".equals(target.trim()))
    4. 4 {
    5. 5 return false;
    6. 6 }
    7. 7
    8. 8 int bl = source.length();
    9. 9 int al = target.length();
    10. 10
    11. 11 for(int bi = 0,ai = 0;bi < al;ai++)
    12. 12 {
    13. 13 if(bi == al || ai == bl)
    14. 14 {
    15. 15 return false;
    16. 16 }
    17. 17 else if(source.charAt(ai) == target.charAt(bi))
    18. 18 {
    19. 19 bi++;
    20. 20 }
    21. 21 }
    22. 22 return true;
    23. 23 }
  5. Levenshtein算法
    1. 1 public static int levenshteinMacth(String source,String target) {
    2. 2 int n = target.length();
    3. 3 int m = source.length();
    4. 4 int[][] d = new int[n + 1][m + 1];
    5. 5
    6. 6 // Step 1
    7. 7 if (n == 0) {
    8. 8 return m;
    9. 9 }
    10. 10
    11. 11 if (m == 0) {
    12. 12 return n;
    13. 13 }
    14. 14
    15. 15 // Step 2
    16. 16 for (int i = 0; i <= n; d[i][0] = i++) {
    17. 17 }
    18. 18
    19. 19 for (int j = 0; j <= m; d[0][j] = j++) {
    20. 20 }
    21. 21
    22. 22 // Step 3
    23. 23 for (int i = 1; i <= n; i++) {
    24. 24 // Step 4
    25. 25 for (int j = 1; j <= m; j++) {
    26. 26 // Step 5
    27. 27 // System.out.println(t.charAt(j - 1));
    28. 28 // System.out.println(s.charAt(i - 1));
    29. 29 // int cost = (t.charAt(j - 1) == s.charAt(i - 1)) ? 0 : 1;
    30. 30 int cost = (source.substring(j - 1, j) == target.substring(i - 1, i) ? 0 : 1);
    31. 31
    32. 32 // Step 6
    33. 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. 34 }
    35. 35 }
    36. 36 // Step 7
    37. 37 return d[n][m];
    38. 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. js中获取jsp中的参数

    碰到一个问题需要再js中根据jsp中request的参数判断执行那段代码 第一种写法: if('${method}'=="add"){js代码段1}else{js代码段2} 第二种 ...

  2. 打印class文件的Java编译器内部的版本号

    当改变了jdk版本时,在编译java时,会遇到Unsupported major.minor version错误.错误信息如下 : Unsupported major.minor version 50 ...

  3. ThinkPHP框架配置自定义的模板变量(十)

    原文:ThinkPHP框架配置自定义的模板变量(十) 模板替换(手册有详细介绍对应的目录) __PUBLIC__:会被替换成当前网站的公共目录 通常是 /Public/ __ROOT__: 会替换成当 ...

  4. SecureCRT 连接虚拟机Linux

    SecureCRT 连接虚拟机Linux   最近在学习linux,在学习中遇到了一些问题,现总结一下. 虚拟机我用的是VirtualBox,完美支持中文,可以在电脑中创建虚拟机环境,上手非常简单.具 ...

  5. 百度词典搜索_dress code

    百度词典搜索_dress code dress code n.着装标准

  6. HDU 3277 Marriage Match III(二分+最大流)

    HDU 3277 Marriage Match III 题目链接 题意:n个女孩n个男孩,每一个女孩能够和一些男孩配对,此外还能够和k个随意的男孩配对.然后有些女孩是朋友,满足这个朋友圈里面的人.假设 ...

  7. cocos2dx 制作单机麻将(一)

    今天開始打算解说下cocos2dx下怎样制作国标麻将 前半部分先解说麻将的逻辑部分,由于都是代码,可能会比較枯燥无聊. 这部分讲完后,你也能够用其它游戏引擎来制作麻将 后半部分,就解说余下的cocos ...

  8. HTML与XML关系分析

    本来这篇是为CSS准备的,但看到视频中CSS和HTML.XML都有关系,即,都是设置他们的样式.而XML和HTML的格式看着也有些类似,就不得不分析一下二者之间的关系了. 要想分析事物关系,要先弄清他 ...

  9. ASP.NET Web Service应用发布到IIs怎么做

    首先把你写的webservice Publish 到 一个文件夹 D:\MyWebService 下,在IIS下的website里面new一个虚拟目录,别名(Alias)随便输一个(这个别名是用于别的 ...

  10. Java垃圾回收机制以及内存泄露

    1.Java的内存泄露介绍 首先明白一下内存泄露的概念:内存泄露是指程序执行过程动态分配了内存,可是在程序结束的时候这块内存没有被释放,从而导致这块内存不可用,这就是内存 泄露,重新启动计算机能够解决 ...