java实现字符串匹配求两个字符串的最大公共子串_java

本文实例讲述了java实现求两个字符串最大公共子串的方法。分享给大家供大家参考,具体如下:

最近在项目工作中有一个关于文本对比的需求,经过这段时间的学习,总结了这篇博客内容:求两个字符串的最大公共子串。

算法思想:基于图计算两字符串的公共子串。具体算法思想参照下图:

输入字符串S1:achmacmh    输入字符串S2:macham

  1. 第a步,是将字符串s1,s2分别按字节拆分,构成一个二维数组;
  2. 二维数组中的值如b所示,比如第一行第一列的值表示字符串s2和s1的第一个字节是否相等,若相等就是1,否则就是0,最终产生b所示的二维数组;
  3. 分别求二维数组中斜线上的公共因子(斜线为元素a右下角值,即a[i][j]的下一个元素是a[i+1][j+1];公共因子为1所在的位置构成的字符串);
  4. 对所有公共因子排序,返回最大的公共因子的值。

具体的实现代码如下所示:

package cn.lulei.compare; 

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List; 

public class StringCompare {
  private int a;
  private int b; 

  public String getMaxLengthCommonString(String s1, String s2) {
    if (s1 == null || s2 == null) {
      return null;
    }
    a = s1.length();//s1长度做行
    b = s2.length();//s2长度做列
    if(a== 0 || b == 0) {
      return "";
    }
    //设置匹配矩阵
    boolean [][] array = new boolean[a][b];
    for (int i = 0; i < a; i++) {
      char c1 = s1.charAt(i);
      for (int j = 0; j < b; j++) {
        char c2 = s2.charAt(j);
        if (c1 == c2) {
          array[i][j] = true;
        } else {
          array[i][j] = false;
        }
      }
    }
    //求所有公因子字符串,保存信息为相对第二个字符串的起始位置和长度
    List<ChildString> childStrings = new ArrayList<ChildString>();
    for (int i = 0; i < a; i++) {
      getMaxSort(i, 0, array, childStrings);
    }
    for (int i = 1; i < b; i++) {
      getMaxSort(0, i, array, childStrings);
    }
    //排序
    sort(childStrings);
    if (childStrings.size() < 1) {
      return "";
    }
    //返回最大公因子字符串
    int max = childStrings.get(0).maxLength;
    StringBuffer sb = new StringBuffer();
    for (ChildString s: childStrings) {
      if (max != s.maxLength) {
        break;
      }
      sb.append(s2.substring(s.maxStart, s.maxStart + s.maxLength));
      sb.append("\n");
    }
    return sb.toString();
  } 

  //排序,倒叙
  private void sort(List<ChildString> list) {
    Collections.sort(list, new Comparator<ChildString>(){
      public int compare(ChildString o1, ChildString o2) {
        return o2.maxLength - o1.maxLength;
      }
    });
  } 

  //求一条斜线上的公因子字符串
  private void getMaxSort(int i, int j, boolean [][] array, List<ChildString> sortBean) {
    int length = 0;
    int start = j;
    for (; i < a && j < b; i++,j++) {
      if (array[i][j]) {
        length++;
      } else {
        sortBean.add(new ChildString(length, start));
        length = 0;
        start = j + 1;
      }
      if (i == a-1 || j == b-1) {
        sortBean.add(new ChildString(length, start));
      }
    }
  } 

  //公因子类
  class ChildString {
    int maxLength;
    int maxStart; 

    ChildString(int maxLength, int maxStart){
      this.maxLength = maxLength;
      this.maxStart = maxStart;
    }
  } 

  /**
   * @param args
   */
  public static void main(String[] args) {
    // TODO Auto-generated method stub
    System.out.println(new StringCompare().getMaxLengthCommonString("achmacmh", "macham"));
  }
}

程序最终执行结果是:

对于两个文件的比对个人认为可以参照这种算法思想(自己现在并为实现),在日后的博客中将会写到。

上述实现过程中,用数组保存了所有的公共子串信息,然后排序取最大的子串,这种做法如果只是求最大子串的话,算法就不是很合理,因此做了如下修改,List只保存当前计算中最大的子串,具体实现如下:

/**
 *@Description: 字符串比较
 */
package com.lulei.test; 

import java.util.ArrayList;
import java.util.List; 

public class StringCompare {
  private int a;
  private int b;
  private int maxLength = -1; 

  public String getMaxLengthCommonString(String s1, String s2) {
    if (s1 == null || s2 == null) {
      return null;
    }
    a = s1.length();//s1长度做行
    b = s2.length();//s2长度做列
    if(a== 0 || b == 0) {
      return "";
    }
    //设置匹配矩阵
    boolean [][] array = new boolean[a][b];
    for (int i = 0; i < a; i++) {
      char c1 = s1.charAt(i);
      for (int j = 0; j < b; j++) {
        char c2 = s2.charAt(j);
        if (c1 == c2) {
          array[i][j] = true;
        } else {
          array[i][j] = false;
        }
      }
    }
    //求所有公因子字符串,保存信息为相对第二个字符串的起始位置和长度
    List<ChildString> childStrings = new ArrayList<ChildString>();
    for (int i = 0; i < a; i++) {
      getMaxSort(i, 0, array, childStrings);
    }
    for (int i = 1; i < b; i++) {
      getMaxSort(0, i, array, childStrings);
    }
    StringBuffer sb = new StringBuffer();
    for (ChildString s: childStrings) {
      sb.append(s2.substring(s.maxStart, s.maxStart + s.maxLength));
      sb.append("\n");
    }
    return sb.toString();
  } 

  //求一条斜线上的公因子字符串
  private void getMaxSort(int i, int j, boolean [][] array, List<ChildString> sortBean) {
    int length = 0;
    int start = j;
    for (; i < a && j < b; i++,j++) {
      if (array[i][j]) {
        length++;
      } else {
        //直接add,保存所有子串,下面的判断,只保存当前最大的子串
        //sortBean.add(new ChildString(length, start));
        if (length == maxLength) {
          sortBean.add(new ChildString(length, start));
        } else if (length > maxLength) {
          sortBean.clear();
          maxLength = length;
          sortBean.add(new ChildString(length, start));
        }
        length = 0;
        start = j + 1;
      }
      if (i == a-1 || j == b-1) {
        //直接add,保存所有子串,下面的判断,只保存当前最大的子串
        //sortBean.add(new ChildString(length, start));
        if (length == maxLength) {
          sortBean.add(new ChildString(length, start));
        } else if (length > maxLength) {
          sortBean.clear();
          maxLength = length;
          sortBean.add(new ChildString(length, start));
        }
      }
    }
  } 

  //公因子类
  class ChildString {
    int maxLength;
    int maxStart; 

    ChildString(int maxLength, int maxStart){
      this.maxLength = maxLength;
      this.maxStart = maxStart;
    }
  } 

  /**
   * @param args
   */
  public static void main(String[] args) {
    // TODO Auto-generated method stub
    System.out.println(new StringCompare().getMaxLengthCommonString("abcdef", "defabc"));
  }
}

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索java
, 字符串匹配算法
, 公共字符串长度
最大公共子串
shell 实现字符串匹配、字符串匹配、正则表达式匹配字符串、python 字符串匹配、php匹配字符串,以便于您获取更多的相关知识。

时间: 2024-09-12 02:37:25

java实现字符串匹配求两个字符串的最大公共子串_java的相关文章

java实现求两个字符串最长公共子串的方法_java

本文实例讲述了java实现求两个字符串最长公共子串的方法.分享给大家供大家参考,具体如下: 这个是华为OJ上的一道题目.首先,如果我们用java写代码,华为OJ有以下三条规则需遵守,否则编译无法通过或者用例无法通过,规则如下: (1)一定不可以有包名: (2)主类名只能为Main: (3)不可以输出与结果无关的信息. 好了,按照以上规则,我们写出来的代码如下(此代码不是最优的,只是用来记录华为OJ上java代码的书写规则): import java.util.Scanner; public cl

C语言求两个字符串的最长公共子串_C 语言

本文实例讲述了C语言求两个字符串的最长公共子串的方法.分享给大家供大家参考.具体实现方法如下: #include "stdio.h" #include "string.h" #include "stdlib.h" void getCommon(char str1[],char str2[],char * str3); int stringLength(char * str); void main(){ char str1[50]; char st

Java实现字符串匹配(基于正则)_java

有一个String,如何查询其中是否有y和f字符?最黑暗的办法就是: 程序1:我知道if.for语句和charAt() class Test{ public static void main(String args[]) { String str="For my money, the important thing "+"about the meeting was bridge-building"; char x='y'; char y='f'; boolean r

java取两个字符串的最大交集_java

本文实例讲述了java取两个字符串的最大交集的实现方法,分享给大家供大家参考.具体实现方法如下: 复制代码 代码如下: package com.itheima.net; public class Game13 {     public static void main(String[] args)     {         String s1 = "135adbfg67";         String s2 = "125dbf59";         Strin

java按字节截取带有汉字的字符串的解法(推荐)_java

由于接口使用的oracle字段长度为固定字节数,然后传进来的字符串估计比数据库字段的总字节数要大,那么截取小于数据库字节数的字符串. 自己参考网上的例子,整了个递归调用就可以了,因为截取的字符字节长度必须小与数据库的字节长度,即如果最后一个字符为汉字,那么只能去掉往前截取. /** * 判断传进来的字符串,是否 * 大于指定的字节,如果大于递归调用 * 直到小于指定字节数 ,一定要指定字符编码,因为各个系统字符编码都不一样,字节数也不一样 * @param s * 原始字符串 * @param

SQLServer中求两个字符串的交集_MsSql

使用javascript的数组来计算,代码如下: 复制代码 代码如下: use tempdb go if (object_id ('fn_getArray' ) is not null ) drop function dbo . fn_getArray go create function fn_getArray (@ inStr1 varchar (8000 ), @ inStr2 varchar (8000 )) returns varchar (8000 ) as begin declar

求两个字符串中的最大相同子串 SubString

package com.itcast.base; public class SubStringTest { public static void main(String[] args) {  String str1 = "ashfjeudccckfjgiccccccjgurhd";  String str2 = "dhfurjcccckgoymjdhccfi";    String max = "";  for (int i = 0; i <

SQLServer中求两个字符串的交集

使用javascript的数组来计算,代码如下: 复制代码 代码如下: use tempdb go if (object_id ('fn_getArray' ) is not null ) drop function dbo . fn_getArray go create function fn_getArray (@ inStr1 varchar (8000 ), @ inStr2 varchar (8000 )) returns varchar (8000 ) as begin declar

Java多线程编程中的两种常用并发容器讲解_java

ConcurrentHashMap并发容器 ConcurrentHashMap可以做到读取数据不加锁,并且其内部的结构可以让其在进行写操作的时候能够将锁的粒度保持地尽量地小,不用对整个ConcurrentHashMap加锁. ConcurrentHashMap的内部结构 ConcurrentHashMap为了提高本身的并发能力,在内部采用了一个叫做Segment的结构,一个Segment其实就是一个类Hash Table的结构,Segment内部维护了一个链表数组,我们用下面这一幅图来看下Con