计算两个字符串的最长公共字串长度(java编程)
2015-08-17 16:01
671 查看
最近在做某公司的在线软件训练题时,遇到了计算两个字符串的最长公共字串长度的求解问题,描述如下:
![](https://img-blog.csdn.net/20150817160416212?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
题目实际完整应叙述为求两个字符串的最长连续公共字串长度,例如: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]的第一个字符到最后一个界限字符(当短字符串已经超出长字符串界限时,该界限字符是长字符串的最后一个字符)。如图:
![](https://img-blog.csdn.net/20150817160450193?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
![](https://img-blog.csdn.net/20150817160504913?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
5, 每一次第二层循环可以得到该次的最长长度,计入一个count数组中,当第一层循环结束时,通过比较获得count数组中最大的数,即是所求的最长长度了。
这里特别说明一下每一次第二层循环得到该次的最长长度的方法:
考虑到类似下面所示的情况:
![](https://img-blog.csdn.net/20150817160555806?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
![](https://img-blog.csdn.net/20150817160616248?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
此在第二层循环中我用了一个临时数组来存储匹配结果,数组的长度为短字符串的长度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},这次循环完后挑出最大值即结束本次第二层循环。
代码如下:
题目实际完整应叙述为求两个字符串的最长连续公共字串长度,例如: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); } }
相关文章推荐
- 数据库链接字符串查询网站
- Flex字符串比较 还有Flex字符串操作
- Ruby中创建字符串的一些技巧小结
- ASP下经常用的字符串等函数参考资料
- 将字符串小写转大写并延时输出的批处理代码
- 将字符串转换成System.Drawing.Color类型的方法
- Lua源码中字符串类型的实现
- Lua性能优化技巧(四):关于字符串
- 字符串聚合函数(去除重复值)
- Ruby中的字符串编写示例
- 总结的5个C#字符串操作方法分享
- sqlserver中求字符串中汉字的个数的sql语句
- sql server字符串非空判断实现方法
- VBS的字符串及日期操作相关函数
- C#实现将千分位字符串转换成数字的方法
- jquery 删除字符串最后一个字符的方法解析
- PowerShell实现在字符串中查找大写字母
- PowerShell中使用Out-String命令把对象转换成字符串输出的例子
- PowerShell中字符串使用单引号和双引号的区别
- Powershell小技巧之获取字符串的行数