动态规划算法之:最长公共子序列 & 最长公共子串(LCS)
来源:互联网 发布:winsock网络编程 编辑:程序博客网 时间:2024/05/18 03:22
1、先科普下最长公共子序列 & 最长公共子串的区别:
找两个字符串的最长公共子串,这个子串要求在原字符串中是连续的。而最长公共子序列则并不要求连续。
2、最长公共子串
其实这是一个序贯决策问题,可以用动态规划来求解。我们采用一个二维矩阵来记录中间的结果。这个二维矩阵怎么构造呢?直接举个例子吧:"bab"和"caba"(当然我们现在一眼就可以看出来最长公共子串是"ba"或"ab")
b a b
c 0 0 0
a 0 1 0
b 1 0 1
a 0 1 0
我们看矩阵的斜对角线最长的那个就能找出最长公共子串。
不过在二维矩阵上找最长的由1组成的斜对角线也是件麻烦费时的事,下面改进:当要在矩阵是填1时让它等于其左上角元素加1。
b a b
c 0 0 0
a 0 1 0
b 1 0 2
a 0 2 0
这样矩阵中的最大元素就是 最长公共子串的长度。
在构造这个二维矩阵的过程中由于得出矩阵的某一行后其上一行就没用了,所以实际上在程序中可以用一维数组来代替这个矩阵。
2.1 代码如下:
01
public
class
LCString2 {
02
03
public
static
void
getLCString(
char
[] str1,
char
[] str2) {
04
int
i, j;
05
int
len1, len2;
06
len1 = str1.length;
07
len2 = str2.length;
08
int
maxLen = len1 > len2 ? len1 : len2;
09
int
[] max =
new
int
[maxLen];
10
int
[] maxIndex =
new
int
[maxLen];
11
int
[] c =
new
int
[maxLen];
// 记录对角线上的相等值的个数
12
13
for
(i =
0
; i < len2; i++) {
14
for
(j = len1 -
1
; j >=
0
; j--) {
15
if
(str2[i] == str1[j]) {
16
if
((i ==
0
) || (j ==
0
))
17
c[j] =
1
;
18
else
19
c[j] = c[j -
1
] +
1
;
20
}
else
{
21
c[j] =
0
;
22
}
23
24
if
(c[j] > max[
0
]) {
// 如果是大于那暂时只有一个是最长的,而且要把后面的清0;
25
max[
0
] = c[j];
// 记录对角线元素的最大值,之后在遍历时用作提取子串的长度
26
maxIndex[
0
] = j;
// 记录对角线元素最大值的位置
27
28
for
(
int
k =
1
; k < maxLen; k++) {
29
max[k] =
0
;
30
maxIndex[k] =
0
;
31
}
32
}
else
if
(c[j] == max[
0
]) {
// 有多个是相同长度的子串
33
for
(
int
k =
1
; k < maxLen; k++) {
34
if
(max[k] ==
0
) {
35
max[k] = c[j];
36
maxIndex[k] = j;
37
break
;
// 在后面加一个就要退出循环了
38
}
39
40
}
41
}
42
}
43
}
44
45
for
(j =
0
; j < maxLen; j++) {
46
if
(max[j] >
0
) {
47
System.out.println(
"第"
+ (j +
1
) +
"个公共子串:"
);
48
for
(i = maxIndex[j] - max[j] +
1
; i <= maxIndex[j]; i++)
49
System.out.print(str1[i]);
50
System.out.println(
" "
);
51
}
52
}
53
}
54
55
public
static
void
main(String[] args) {
56
57
String str1 =
new
String(
"123456abcd567"
);
58
String str2 =
new
String(
"234dddabc45678"
);
59
// String str1 = new String("aab12345678cde");
60
// String str2 = new String("ab1234yb1234567");
61
getLCString(str1.toCharArray(), str2.toCharArray());
62
}
63
}
LCS的java算法---考虑可能有多个相同的最长公共子串
http://blog.csdn.net/rabbitbug/article/details/1740557
最大子序列、最长递增子序列、最长公共子串、最长公共子序列、字符串编辑距离
http://www.cnblogs.com/zhangchaoyang/articles/2012070.html
2.2 其实 awk 写起来也很容易:
1
echo
"123456abcd567
2
234dddabc45678
"|awk -vFS="
" 'NR==1{str=$0}NR==2{N=NF;for(n=0;n++<N;){s="
";for(t=n;t<=N;t++){s=s"
"$t;
if
(index(str,s)){a[n]=t-n;b[n]=s;
if
(m<=a[n])m=a[n]}
else
{t=N}}}}END{
for
(n=0;n++<N;)
if
(a[n]==m)print b[n]}'
ref:http://bbs.chinaunix.net/thread-4055834-2-1.html
2.3 perl的。。。真心没看懂。。。
01
#!/usr/bin/perl
02
use
strict;
03
use
warnings;
04
05
my
$str1
=
"123456abcd567"
;
06
my
$str2
=
"234dddabc45678"
;
07
my
$str
=
$str1
.
"\n"
.
$str2
;
08
09
my
(
@substr
,
@result
);
10
$str
=~ /(.+)(?=.*\n.*\1)(*PRUNE)(?{
push
@substr
,
$1
})(*F)/;
11
@substr
=
sort
{
length
(
$b
) <=>
length
(
$a
) }
@substr
;
12
@result
=
grep
{
length
==
length
$substr
[0] }
@substr
;
13
print
"@result\n"
;
3、最长公共子序列
01
import
java.util.Random;
02
03
public
class
LCS {
04
05
public
static
void
main(String[] args) {
06
07
// 随机生成字符串
08
// String x = GetRandomStrings(substringLength1);
09
// String y = GetRandomStrings(substringLength2);
10
String x =
"a1b2c3"
;
11
String y =
"1a1wbz2c123a1b2c123"
;
12
// 设置字符串长度
13
int
substringLength1 = x.length();
14
int
substringLength2 = y.length();
// 具体大小可自行设置
15
16
// 构造二维数组记录子问题x[i]和y[i]的LCS的长度
17
int
[][] opt =
new
int
[substringLength1 +
1
][substringLength2 +
1
];
18
19
// 从后向前,动态规划计算所有子问题。也可从前到后。
20
for
(
int
i = substringLength1 -
1
; i >=
0
; i--) {
21
for
(
int
j = substringLength2 -
1
; j >=
0
; j--) {
22
if
(x.charAt(i) == y.charAt(j))
23
opt[i][j] = opt[i +
1
][j +
1
] +
1
;
// 状态转移方程
24
else
25
opt[i][j] = Math.max(opt[i +
1
][j], opt[i][j +
1
]);
// 状态转移方程
26
}
27
}
28
System.out.println(
"substring1:"
+ x);
29
System.out.println(
"substring2:"
+ y);
30
System.out.print(
"LCS:"
);
31
32
int
i =
0
, j =
0
;
33
while
(i < substringLength1 && j < substringLength2) {
34
if
(x.charAt(i) == y.charAt(j)) {
35
System.out.print(x.charAt(i));
36
i++;
37
j++;
38
}
else
if
(opt[i +
1
][j] >= opt[i][j +
1
])
39
i++;
40
else
41
j++;
42
}
43
}
44
45
// 取得定长随机字符串
46
public
static
String GetRandomStrings(
int
length) {
47
StringBuffer buffer =
new
StringBuffer(
"abcdefghijklmnopqrstuvwxyz"
);
48
StringBuffer sb =
new
StringBuffer();
49
Random r =
new
Random();
50
int
range = buffer.length();
51
for
(
int
i =
0
; i < length; i++) {
52
sb.append(buffer.charAt(r.nextInt(range)));
53
}
54
return
sb.toString();
55
}
56
}
字符串最大公共子序列以及最大公共子串问题
http://gongqi.iteye.com/blog/1517447
动态规划算法解最长公共子序列LCS问题
http://blog.csdn.net/v_JULY_v/article/details/6110269
- 面试(动态规划算法之:最长公共子序列 & 最长公共子串(LCS))
- 动态规划算法之:最长公共子序列 & 最长公共子串(LCS)
- 动态规划算法之:最长公共子序列 & 最长公共子串(LCS)
- 动态规划算法之:最长公共子序列 & 最长公共子串(LCS)
- 动态规划算法之:最长公共子序列 & 最长公共子串(LCS)
- 算法12—动态规划算法之:最长公共子序列 & 最长公共子串(LCS)
- 算法之动态规划2(LCS最长公共子序列, edit distance,交叉子串)
- 算法之动态规划(LCS最长公共子序列, edit distance,交叉子串)
- 算法导论-----最长公共子序列LCS(动态规划)
- 动态规划之最长公共子序列(lcs)
- 动态规划之最长公共子序列(lcs)
- 动态规划之最长公共子序列(LCS)
- 动态规划之最长公共子序列(LCS)
- 动态规划入门之最长公共子序列(LCS)
- 动态规划之最长公共子序列 (LCS )
- 动态规划之最长公共子序列(LCS)
- 动态规划之最长公共子序列问题(LCS)
- 动态规划之最长公共子序列问题(LCS)
- gcc常用参数
- 编写一个函数,作用是把一个char组成的字符串循环右移n个
- HDU 1824 Let's go home
- 关于2的补码
- dfs--poj1979
- 动态规划算法之:最长公共子序列 & 最长公共子串(LCS)
- IOS 中通过URL Schemes让一个应用程序启动另一个指定应用程序
- UVa 11806 Cheerleaders (组合&逆向思维||容斥定理)
- POJ 3207 Ikki's Story IV - Panda's Trick (2-sat,4级)
- 混音器原理及Mixer API函数介绍
- 面试题。。虽然没有答案,但是能激发自己的想象
- 并发服务器:多路复用I/O
- 浮点数的二进制表示
- linux zip压缩命令解压命令