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"));
  }
}

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

(0)

相关推荐

  • Python最长公共子串算法实例

    本文实例讲述了Python最长公共子串算法.分享给大家供大家参考.具体如下: #!/usr/bin/env python # find an LCS (Longest Common Subsequence). # *public domain* def find_lcs_len(s1, s2): m = [ [ 0 for x in s2 ] for y in s1 ] for p1 in range(len(s1)): for p2 in range(len(s2)): if s1[p1] =

  • C++实现寻找最低公共父节点的方法

    本文实例讲述了C++实现寻找最低公共父节点的方法,是数据结构中二叉树的经典算法.分享给大家供大家参考.具体方法如下: 最低公共父节点,意思很好理解. 思路1:最低公共父节点满足这样的条件:两个节点分别位于其左子树和右子树,那么定义两个bool变量,leftFlag和rightFlag,如果在左子树中,leftFlag为true,如果在右子树中,rightFlag为true,仅当leftFlag == rightFlag == true时,才能满足条件. 实现代码如下: #include <ios

  • 深入解析最长公共子串

    题目:如果字符串一的所有字符按其在字符串中的顺序出现在另外一个字符串二中,则字符串一称之为字符串二的子串.注意,并不要求子串(字符串一)的字符必须连续出现在字符串二中.请编写一个函数,输入两个字符串,求它们的最长公共子串,并打印出最长公共子串.例如:输入两个字符串BDCABA和ABCBDAB,字符串BCBA和BDAB都是是它们的最长公共子串,则输出它们的长度4,并打印任意一个子串. 分析:求最长公共子串(Longest Common Subsequence, LCS)是一道非常经典的动态规划题,

  • JavaScript自定义函数实现查找两个字符串最长公共子串的方法

    本文实例讲述了JavaScript自定义函数实现查找两个字符串最长公共子串的方法.分享给大家供大家参考,具体如下: //查找两个字符串的最长公共子串 function findSubStr(s1,s2){ var S=sstr= "" ,L1=s1.length,L2=s2.length; if (L1>L2){ var s3=s1;s1=s2,s2=s3,L1=s2.length;} for ( var j=L1;j> 0 ;j--) for ( var i= 0 ;i&

  • Ruby实现的最长公共子序列算法

    最长公共子序列,LCS,动态规划实现. #encoding: utf-8 #author: xu jin, 4100213 #date: Nov 01, 2012 #Longest-Commom-Subsequence #to find a longest commom subsequence of two given character arrays by using LCS algorithm #example output: #The random character arrays are

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

  • 利用C++实现最长公共子序列与最长公共子串

    一.问题描述 子串应该比较好理解,至于什么是子序列,这里给出一个例子:有两个母串 cnblogs belong 比如序列bo, bg, lg在母串cnblogs与belong中都出现过并且出现顺序与母串保持一致,我们将其称为公共子序列.最长公共子序列(Longest Common Subsequence, LCS),顾名思义,是指在所有的子序列中最长的那一个.子串是要求更严格的一种子序列,要求在母串中连续地出现.在上述例子的中,最长公共子序列为blog(cnblogs, belong),最长公共

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

    本文实例讲述了java实现求两个字符串最大公共子串的方法.分享给大家供大家参考,具体如下: 最近在项目工作中有一个关于文本对比的需求,经过这段时间的学习,总结了这篇博客内容:求两个字符串的最大公共子串. 算法思想:基于图计算两字符串的公共子串.具体算法思想参照下图: 输入字符串S1:achmacmh    输入字符串S2:macham 第a步,是将字符串s1,s2分别按字节拆分,构成一个二维数组: 二维数组中的值如b所示,比如第一行第一列的值表示字符串s2和s1的第一个字节是否相等,若相等就是1

  • PHP实现求两个字符串最长公共子串的方法示例

    本文实例讲述了PHP实现求两个字符串最长公共子串的方法.分享给大家供大家参考,具体如下: 前面一篇PHP实现求解最长公共子串问题的方法是基于java改进而来,这里再来看另一种公共子串算法. 代码如下: <?php $a = 'abceee12345309878'; $b = 'abceeew2345i09878fsfsfsfabceeewsfsdfsfsabceeew'; $c = array(); $lenht1 = strlen($a); $lenth2 = strlen($b); $sta

  • Python求两个字符串最长公共子序列代码实例

    一.问题描述 给定两个字符串,求解这两个字符串的最长公共子序列(Longest Common Sequence).比如字符串1:BDCABA:字符串2:ABCBDAB.则这两个字符串的最长公共子序列长度为4,最长公共子序列是:BCBA 二.算法求解 这是一个动态规划的题目.对于可用动态规划求解的问题,一般有两个特征:①最优子结构:②重叠子问题 ①最优子结构 设X=(x1,x2,...,xn)和Y=(y1,y2,...,ym)是两个序列,将X和Y的最长公共子序列记为LCS(X,Y) 找出LCS(X

  • Java实现字符串匹配的示例代码

    目录 java实现字符串匹配 暴力匹配 KMP算法 java实现字符串匹配 暴力匹配 /** * 暴力匹配 * * @param str1 需要找的总字符串 * @param str2 需要找到的字符串 * @return 找到的字符串的下标 */ private static int violence(String str1, String str2) { char[] s1 = str1.toCharArray(); char[] s2 = str2.toCharArray(); int s

  • c语言求两个字符串的交集

    目录 一.main()函数 二.fun1()函数 三.fun2()函数 注意; 总结 求两个字符串的交集,看似简单,实则需要考虑的细节很多. 我的思路: 1.将两个字符串简化,将里面重复的字母减少为一个. 2.拼接两个字符串,借助循环把重复出现两次的字符找出来. 有了思路开始写代码. 一.main()函数 思路: 1.定义两个储存字符串的数组tt[M],pp[M] 2.定义指针*p接收fun2() 返回值,输出交集 3.输入两个字符串(此处注意越界问题) 4.调用函数 5.输出交集 #inclu

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

    如下所示: # coding:utf-8 ''' 求两个字符串的最长公共子串 思想:建立一个二维数组,保存连续位相同与否的状态 ''' def getNumofCommonSubstr(str1, str2): lstr1 = len(str1) lstr2 = len(str2) record = [[0 for i in range(lstr2+1)] for j in range(lstr1+1)] # 多一位 maxNum = 0 # 最长匹配长度 p = 0 # 匹配的起始位 for

  • Java获取两个字符串中最大相同子串的方法

    "abcwerthelloyuiodef" "cvhellobnm" 思路: 1,将短的那个子串按照长度递减的方式获取到. 2,将每获取到的子串去长串中判断是否包含,如果包含,已经找到! class StringTest3 { public static String getMaxSubString(String s1,String s2) { String max = "",min = ""; max = (s1.lengt

随机推荐