查找两个字符串a,b中的最长公共子串
2016-06-27 17:46
1121 查看
题目描述
查找两个字符串a,b中的最长公共子串 输入描述:
输入两个字符串
输出描述:
返回重复出现的字符
输入例子:
abcdefghijklmnop abcsafjklmnopqrstuvw
输出例子:
jklmnop
解法一:
import java.util.*; public class Main{ public static void main(String[] args){ Scanner in = new Scanner(System.in); while(in.hasNext()){ String s1 = in.nextLine(); String s2 = in.nextLine(); String max = s1.length() >= s2.length()?s1:s2; String min = s1.length() >= s2.length()?s2:s1; int l = 0; String s =""; for(int i=0;i<min.length();i++){ for(int j=i+1;j<=min.length();j++){ if(max.contains(min.substring(i,j)) && j-i>l){ l=j-i; s=min.substring(i,j); } } } System.out.println(s); } } }
解法二:
012算法笔记——【动态规划】最长公共子串问题
1、问题相关定义:
(1)字符串:一个字符串S是将n 个字符顺次排列形成的数组, n称为S的长度,表示为len(S) 。S的第i字符表示为S[ i ]。
(2)子串:字符串S的子串S[ i:j ] ( i ≤ j)表示S串中从i到j这一段,也就是排列S[ i ] , S[ i + 1 ] , ⋯,S[ j ] 形成的字符串。
(3)后缀:后缀是指从某个位置i开始到整个串末尾结束的一个特殊子串。字符串S的从i开头的后缀表示为Suffix( S,i) ,也就是Suffix( S, i) = S[ i:len ( S) ]。
(4)公共后缀:字符串U 如果既是字符串S的后缀又是字符串T的后缀,则字符串U 是字符串S和T的一个公共后缀。
(5)最长公共后缀:字符串S和T的最长公共后缀是指字符串S和T的所有公共后缀中长度最大的子串。
(4)公共子串:字符串U 如果既是字符串S的子串又是字符串T的子串,则字符串U 是字符串S和T的一个公共子串。
(5)最长公共子串:字符串S和T的最长公共子串是指字符串S和T的所有公共子串中长度最大的子串。
例:给定2 个长度分别为4, 4 的字符串“abab”,“baba”,它们的公共子串(Common Substring) 有“”,“a”,“b”,“ab”,“ba”,“aba”,“bab”。其中最长公共子串(LCS) 即为“aba”或“bab”。
2、动态规划求解
在使用动态规划求解2个长度分别为p, q的字符串S,T的最长公共子串问题前,先给出求它们任意前缀子串对S[1:i],T[1:j]的最长公共后缀的算法,其中:1 ≤ i ≤ p,1 ≤ j ≤ q。设LCSuffix(S[1:i],T[1:j])表示前缀子串对S[1: i] ,T[1:j] 的最长公共后缀,则该问题的递推关系式如下:
例如:字符串S“baba”, T“abab”, 使用上面递推关系式求得字符串S, T所有前缀子串对的最长公共后缀,如下表所示:
字符串S, T所有前缀子串对应的最长公共后缀中长度最大的即为字符串S, T的最长公共子串,即:
其中LCS(
S,T) 表示字符串S, T的最长公共子串。对于字符串S“baba”, T“abab”,从表1中可以看出它们的最长公共后缀中长度最大为3,对应两个最长公共子串,即:"aba"和"bab"。
// CPPPRO.cpp : 定义控制台应用程序的入口点。 //3m6 最长公共子串,动态规划实现 #include "stdafx.h" #include <iostream> #include <string> using namespace std; string getLCSLength(string &s, string &t); int main() { string s,t; cout<<"请输入字符串s:"<<endl; cin>>s; cout<<"请输入字符串t:"<<endl; cin>>t; cout<<"最长公共子串为:"<<endl; cout<<getLCSLength(s,t)<<endl; return 0; } string getLCSLength(string &s, string &t) { int p = s.length(); int q = t.length(); string **num = new string *[p]; for(int i=0;i<p;i++) { num[i] = new string[q]; } char char1 = '\0'; char char2 = '\0'; int len = 0; string lcs = "" ; for(int i=0; i<p; i++) { for (int j=0; j<t.length(); j++) { char1 = s.at(i); char2 = t.at(j); if(char1!=char2) { num[i][j] = "" ; } else { if (i==0||j==0) { num[i][j]=char1; } else { num[i][j]=num[i-1][j-1]+char1; } if(num[i][j].length()>len) { len = num[i][j].length() ; lcs = num[i][j]; } else if(num[i][j].length()==len) { lcs = lcs + "," + num[i][j]; } } } } for(int i=0;i<p;i++) { delete[] num[i]; } delete[] num; return lcs; }<span style="font-family:Arial;color:#333333;"><span style="font-size: 14px; line-height: 26px;"> </span></span>
程序运行结果如下:
使用动态规划算法求2个长度分别为p, q的字符串S, T的最长公共子串需要构造一个二维表,该二维表含有pq个项,使用递推的方法求每项的时间负责度为O (1) ,所以求出所有项的时间复杂度为O (pq) 。在二维表中只需找到一个最大值项,其对应于原2个字符串的最长公共子串,因此使用动态规划算法的时间复杂度为O (pq) 。
建立2个长度分别为p, q的字符串S, T的广义后缀数组的时间复杂度为O (p + q) ,求广义后缀数组中相邻子串的最长公共前缀的时间复杂度为<O(p + q) ,O(1)>,即需要预处理时间复杂度为O(p + q) ,每次查询最长公共前缀的时间复杂度为O(1) 。遍历所有最长公共前缀的时间复杂度为O(p+q) ,因此使用广义后缀数组解决最长公共子串的时间复杂度为O(p+q) 。对于字符串S, T,它的广义后缀数组在不降低性能同时需要使用2
(p + q) 空间。
解决2个长度分别为p, q的字符串最长公共子串问题的动态规划算法,广义后缀树算法以及广义后缀数组算法在时间复杂度,空间复杂度以及编程实现上的比较分析总结如下表所示:
其中动态规划算法以及广义后缀树算法的研究已经非常成熟,在计算机算法领域有着各种各样的应用,但在解决字符串最长公共子串问题上还有一定不足,即动态规划算法占用的时间复杂度以及空间复杂度都很高,而广义后缀树算法虽然降低了时间复杂度,但其空间复杂度还是较高,另外编程实现也较难。虽然广义后缀数组的理论研究还在发展中,但就目前的研究成果而言,在解决字符串最长公共子串问题上,根据上面给出的算法,它可以综合动态规划算法以及广义后缀树算法的优点,既保证了线性的时间复杂度,较低的空间复杂度又易于编程实现。改进的后缀数组算法及相关定义应用可查看博文《最长公共子串问题的后缀数组解法》。
相关文章推荐
- thinkphp 3.2.3 单字符方法汇总
- 【C#中的as和强制转换的区别】
- $ionicConfigProvider-ionic 中默认安装后tap导航在顶部怎么j解决
- Foundation中String对象常用API
- [转]JavaScript 节流函数 Throttle 详解
- phpcms上传提示找不到临时文件夹/目录(解决方法)
- 实现进程单例的一些想法
- BZOJ1237: [SCOI2008]配对
- JavaWeb学习总结(十二)——Session
- Leetcode-search-insert-position
- 异常值的观测
- 自定义选择器(同时支持单滚轮和双滚轮联动选择器)
- 第四专题 Problem J
- MySQL出现SQL Error (2013)连接错误的解决方法
- amq笔记:记一个关于PooledConnectionFactory的问题
- iOS 归档解档
- 【开源】.Net 动态脚本引擎NScript
- 模拟器键盘Can't find keyplane that supports type 4 for keyboard iPhone-PortraitChoco-NumberPad
- javaweb学习总结(十一)——使用Cookie进行会话管理
- text()/html()/val()的区别