您的位置:首页 > 编程语言 > Java开发

计算两个字符串的最长公共字串长度(java编程)

2015-08-17 16:01 671 查看
最近在做某公司的在线软件训练题时,遇到了计算两个字符串的最长公共字串长度的求解问题,描述如下:



         题目实际完整应叙述为求两个字符串的最长连续公共字串长度,例如:ABCDEF 和ABDEF应是3而不是5。

         输入是以空格为分隔的两个字符串,输出是一个int型整数。

         本文以全字母情况为例进行说明,程序中判断时不区分大小写,算法说明中为方便匹配全部以大写为例。

         算法大致如下:

1,  将输入以空格为标志分割为s[0]和s[1]两个字符串。

2,  比较两个字符串的长度,通过处理,保证短字符串为s[0],长字符串为s[1],相等则不用交换,方便下文的比较匹配。

3,  将s[0]和s[1]转换为字符数组便于循环处理(下文仍以s[0]和s[1]字符串来叙述)。

4,  以长字符串s[1]为准,建立两层循环:第一层负责s[0]头字符匹配的起始位置移动,从长字符串s[1]的第一个字符到最后一个字符;第二层负责s[0]字符串内的每个字符与s[1]的循环匹配,从短字符串s[0]的第一个字符到最后一个界限字符(当短字符串已经超出长字符串界限时,该界限字符是长字符串的最后一个字符)。如图:





5,  每一次第二层循环可以得到该次的最长长度,计入一个count数组中,当第一层循环结束时,通过比较获得count数组中最大的数,即是所求的最长长度了。

 

这里特别说明一下每一次第二层循环得到该次的最长长度的方法:

考虑到类似下面所示的情况:


                             

 
   

此在第二层循环中我用了一个临时数组来存储匹配结果,数组的长度为短字符串的长度s[0],因为不可能比s[0]更长了,临时数组的所有值默认初始化为0,当从第一个字符开始匹配时,如果匹配成功,则临时数组内数字下标为0对应的数字+1,并继续匹配,如果匹配失败,则跳到下一个字符,数组中的数字下标也+1,以此类推。因此,MEFDPFRH图例所得的数组应为{0,0,0,1,1,1,0,0},而RBCVEFGH图例所得的数组应该为{0,2,4,0,0,0,0,0},这次循环完后挑出最大值即结束本次第二层循环。

 

代码如下:

/**
* 求两个字符串的最长连续公共字符串长度
* @author 田蜜杰果
* @date   2015/08/17
*/
import java.util.Scanner;

public class Main10 {
public static void main(String[] args) {
//1.将输入以空格为标志分割为s[0]和s[1]两个字符串
Scanner sc=new Scanner(System.in);
String input=sc.nextLine().trim();
sc.close();
//判断输入是否至少是两个字符串,当然,如果字符串的数量大于2,只会操作前两个,后面的字符串抛弃。
if(input.indexOf(" ")==-1){
System.exit(0);//如果没有找到空格,那么输入有误,直接结束
}
String[] s=input.split(" ");
//2,比较两个字符串的长度,保证短字符串为s[0],长字符串为s[1],相等则不用交换
if(s[0].length()>s[1].length()){
String temp=s[0];
s[0]=s[1];
s[1]=temp;
}
//3,将s[0]和s[1]转换为字符数组便于循环处理
char[] s0_char=s[0].toCharArray();
char[] s1_char=s[1].toCharArray();
int[] count=new int[s[1].length()];//统计数组,用于保存每次第一层循环匹配的结果,用于最后进行最大长度筛选
//4,以长字符串s[1]为准,建立两层循环
for(int start=0,end=s[0].length()-1;start<s[1].length();start++){
int[] temp=new int[s[0].length()];//新建一个临时数组来存储匹配结果,数组的长度为短字符串的长度s[0]
int tempN=0;//临时数组内的数字下标
for(int j=start;j<=end;j++){
//如果匹配成功,则该数字+1,并继续匹配
//匹配的时候,考虑了大小写,所以if中的条件有3个,这里使用了截断或||
if((s1_char[j]==s0_char[j-start])||(s1_char[j]==s0_char[j-start]+32)||(s1_char[j]==s0_char[j-start]-32)){//忽略大小写
temp[tempN]+=1;
}else{ //如果匹配失败,临时数组内的数字下标+1
tempN++;
}
//找出本次循环匹配的临时数组中最大长度
int max_temp=temp[0];
for(int k=1;k<temp.length;k++){   //找出每次匹配最长的个数,这是为了防止出现匹配时非连续公共串,比如110111这算3个而不是5,101101这算2个而不是4
if(temp[k]>max_temp){
max_temp=temp[k];
}
}
count[start]=max_temp;//将该次循环最大长度赋值给统计数组中对应位置的元素
}
//判断结束字符的位置,如果短字符的末尾已经超出长字符串末尾了,那么比较的结尾字符应该是长字符串的最后一个字符
if(end>=s[1].length()-1){
end=s[1].length()-1;
}else{
end++;
}
}
//找出统计数组中最大的数字
int max=count[0];
for(int k=1;k<count.length;k++){
if(count[k]>max){
max=count[k];
}
}
//输出结果
System.out.println(max);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息