求多个字符串中,最长的公共子串?

qq_33086215 2016-08-02 05:52:38
比如 ABCDEFG ABCDEQWE 公共子串就是ABCDE
小弟初学java,听说这个论坛有好多大牛! 希望前辈能写一个简单易懂的代码,帮助理解! 感激不尽!
...全文
816 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
拿后缀数组,二分求
sky_08_06_02 2016-08-20
  • 打赏
  • 举报
回复
get it
qq_33086215 2016-08-04
  • 打赏
  • 举报
回复
引用 1 楼 Hiel_Wang 的回复:
写了一个版本,效率肯定不高,但是希望能理解

import java.io.*;
 
public class Main {
      public static void main(String[] args)  throws IOException, InterruptedException {
          String s1 = "ABCDEFG";
          String s2 ="ABCDEQWE     ";
          	
          label:
          for (int subStrLength = s1.length(); subStrLength > 0; subStrLength--)
        	  for (int index = 0; index + subStrLength <= s1.length(); index++) { 
        		  //两层循环的意思把第一个字符串s1拆分
        		  //长度为7:ABCDEFG,长度为6:BCDEFG,ABCDEF,长度为5,ABCDE,BCDEF,CDEFG...长度为1,A,B,C,D,E,F,G
        		  //把拆分的字符串赋给变量subString
        		  String subString = s1.substring(index, index+subStrLength);
        		  //可以把下面代码注释掉,打印出subString的值:System.out.println(subStrLength + ":" + subString);
        		  if (-1 != s2.indexOf(subString)) {
        			  //如果在第二个字符串中找到了拆分好的字符串subString,那么subString就是最长的公共子串,然后跳出所有的循环
        			  System.out.println(subString);
        			  break label;
        		  }
        		  		
        	  }
      }
}



思路好清晰啊!  多谢前辈
nikyotensai 2016-08-03
  • 打赏
  • 举报
回复
引用 4 楼 NewMoons 的回复:
说明:求二个字符串中最长的公共子串。 思路:找出比较字符串中较短的那个,然后从这个字符串从长往短逐次遍历和另一个字符串比较,直到发现位置。 由于最长公共子串可能不止一个,也可能重复,所以这里Set集合输出所有结果,并去掉了重复的公共子串,如果 需要输出重复的,将Set改成List即可。 这里只实现了了2个字符串的比较,如果多于两个,思路类似,只是比较时不能只拿最短的比较,需要逐次从小到大选择 最短字符串和剩余字符串比较,中间变量先存起来,一旦有更长的则替换之。

public class Test {

	public Test() {
		// TODO Auto-generated constructor stub
	}
	
	public static Set<String> maxCommonStr(String str1, String str2){
		if(str1 == null || str2 == null){
			return null;
		}
		
		if("".equals(str1) || "".equals(str2)){
			return null;
		}
		
		//此算法选择长度短的字符串作外循环比较字符串,因为公共字符串的长度肯定小于短的字符串。
		if(str1.length() > str2.length()){
			String shortStr;
			shortStr = str2;
			str2 = str1;
			str1 = shortStr;
		}
		
		String tempStr;
		Set<String> set = new HashSet<String>();
		boolean hasFinded = false;
		//外层循环控制比较字符串的长度。
		for(int i=str1.length();i>=1;i--){
			//内层循环负责遍历所有当前长度的字符串。
			for(int j=0;(j+i)<=str1.length();j++){
				tempStr = str1.substring(j, j+i);
				if(str2.contains(tempStr)){
					set.add(tempStr);
					//由于可能有其它相同长度的公共字符串,所以找到一个后本层循环不能退出。
					hasFinded = true;
				}
			}
			if(hasFinded){
				break;
			}
		}
		
		return set;
	}

	public static void main(String[] args) {
		String str1 = "12ABCDEFG23457";
		String str2 = "ABCDEQW23457E57";
		
		Set<String> set = Test.maxCommonStr(str1, str2);
		
		if(set == null || set.size() == 0){
			System.out.println("报告!没有发现公共字符串!");
		}else{
			for(String str : set){
				System.out.println(str);
			}
		}
	}

}
经验差距呀
NewMoons 2016-08-03
  • 打赏
  • 举报
回复
说明:求二个字符串中最长的公共子串。 思路:找出比较字符串中较短的那个,然后从这个字符串从长往短逐次遍历和另一个字符串比较,直到发现位置。 由于最长公共子串可能不止一个,也可能重复,所以这里Set集合输出所有结果,并去掉了重复的公共子串,如果 需要输出重复的,将Set改成List即可。 这里只实现了了2个字符串的比较,如果多于两个,思路类似,只是比较时不能只拿最短的比较,需要逐次从小到大选择 最短字符串和剩余字符串比较,中间变量先存起来,一旦有更长的则替换之。

public class Test {

	public Test() {
		// TODO Auto-generated constructor stub
	}
	
	public static Set<String> maxCommonStr(String str1, String str2){
		if(str1 == null || str2 == null){
			return null;
		}
		
		if("".equals(str1) || "".equals(str2)){
			return null;
		}
		
		//此算法选择长度短的字符串作外循环比较字符串,因为公共字符串的长度肯定小于短的字符串。
		if(str1.length() > str2.length()){
			String shortStr;
			shortStr = str2;
			str2 = str1;
			str1 = shortStr;
		}
		
		String tempStr;
		Set<String> set = new HashSet<String>();
		boolean hasFinded = false;
		//外层循环控制比较字符串的长度。
		for(int i=str1.length();i>=1;i--){
			//内层循环负责遍历所有当前长度的字符串。
			for(int j=0;(j+i)<=str1.length();j++){
				tempStr = str1.substring(j, j+i);
				if(str2.contains(tempStr)){
					set.add(tempStr);
					//由于可能有其它相同长度的公共字符串,所以找到一个后本层循环不能退出。
					hasFinded = true;
				}
			}
			if(hasFinded){
				break;
			}
		}
		
		return set;
	}

	public static void main(String[] args) {
		String str1 = "12ABCDEFG23457";
		String str2 = "ABCDEQW23457E57";
		
		Set<String> set = Test.maxCommonStr(str1, str2);
		
		if(set == null || set.size() == 0){
			System.out.println("报告!没有发现公共字符串!");
		}else{
			for(String str : set){
				System.out.println(str);
			}
		}
	}

}
nikyotensai 2016-08-03
  • 打赏
  • 举报
回复
for (int j = 0; j < s2.length(); j--)改成for (int j = 0; j < s2.length()&&j<i; j--) 失误
nikyotensai 2016-08-03
  • 打赏
  • 举报
回复
public static void main(String[] args) { // TODO Auto-generated method stub String s1 = "qwertyui"; String s2 = "tyui"; String s3 = ""; for (int i = s2.length(); i > 0; i--) { for (int j = 0; j < s2.length(); j--) { if (s1.contains(s2.substring(j, i))) { s3 = s2.substring(j, i); break; } } if(s3!="") break; } System.out.println(s3); } 短的那个作为s2,你可以自己比较一下
Hiel_Wang 2016-08-03
  • 打赏
  • 举报
回复
写了一个版本,效率肯定不高,但是希望能理解

import java.io.*;
 
public class Main {
      public static void main(String[] args)  throws IOException, InterruptedException {
          String s1 = "ABCDEFG";
          String s2 ="ABCDEQWE     ";
          	
          label:
          for (int subStrLength = s1.length(); subStrLength > 0; subStrLength--)
        	  for (int index = 0; index + subStrLength <= s1.length(); index++) { 
        		  //两层循环的意思把第一个字符串s1拆分
        		  //长度为7:ABCDEFG,长度为6:BCDEFG,ABCDEF,长度为5,ABCDE,BCDEF,CDEFG...长度为1,A,B,C,D,E,F,G
        		  //把拆分的字符串赋给变量subString
        		  String subString = s1.substring(index, index+subStrLength);
        		  //可以把下面代码注释掉,打印出subString的值:System.out.println(subStrLength + ":" + subString);
        		  if (-1 != s2.indexOf(subString)) {
        			  //如果在第二个字符串中找到了拆分好的字符串subString,那么subString就是最长的公共子串,然后跳出所有的循环
        			  System.out.println(subString);
        			  break label;
        		  }
        		  		
        	  }
      }
}

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧