1、 找出最长公共子序列的长度(Longest Common Sequence)
题:求字符串str1,str2的最长公共子序列的长度(可以不连续)。
解:定义二元函数函数f(m,n):分别以str1[m],str2[n]结尾的连续公共子序列的长度
而对于f(m,n) 有以下两种情况
1.str1[m] != str2[n],则有f(m,n) = max(f(m-1,n), f(m, n-1))
2.str1[m] == str2[n],则有f(m,n) = f(m-1,n-1) + 1
另外f(0,j) = 0(j>=0)
f(j,0) = 0 (j>=0)
2、 找出两个字符串的最长公共子串(Longest Common Substring)
1.找两个字符串的最长公共子串,(注意不是子序列,子串是连续的)这个子串要求在原字符串中是连续的。
思想一:矩阵
我们采用一个二维矩阵来记录中间的结果。这个二维矩阵怎么构造呢?直接举个例子吧:”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
这样矩阵中的最大元素就是最长公共子串的长度。
在构造这个二维矩阵的过程中由于得出矩阵的某一行后其上一行就没用了,所以实际上在程序中可以用一维数组来代替这个矩阵。
思想二:动规
求字符串str1,str2的最长公共子串的长度。
定义二元函数函数f(m,n):分别以str1[m],str2[n]结尾的连续公共子串的长度
而对于f(m,n) 有以下两种情况
1.str1[m] != str2[n],则有f(m,n) =0
2.str1[m] == str2[n],则有f(m,n) = f(m-1,n-1) + 1
另外f(0,j) = 0(j>=0)
f(j,0) = 0 (j>=0)
考虑到f(m,n) 与上一行数据及该行靠左的数据有关,可以把数组空间压缩,每行从右往左计算出值
思想三:后缀树
组个字符串,要求将第一个字符串与#相连,再与第二个字符串相连,以$结束,将该字符串建立后缀树,遍历找出子结点同时包含#(因为每个后缀子串都会以$结束,所以这里就看子结点是否包含#,包含说明是第一个字串)的最长公共结点,即为所求。
3、 找出一个字符串的最长回文子串
根据回文的特性,设字符串为str1,将字符串倒序生成str2,该问题可转换为求str1和str2的最长公共子串(LCS)长度
4、 找出数组元素和最大子序列
数组元素和最大子序列是要找出由数组成的一维数组中和最大的连续子序列。比如{5,-3,4,2}的最大子序列就是{5,-3,4,2},它的和是8,达到最大;而{5,-6,4,2}的最大子序列是{4,2},它的和是6。你已经看出来了,找最大子序列的方法很简单,只要前n项的和还没有小于0那么子序列就一直向后扩展,否则丢弃之前的子序列开始新的子序列,同时我们要记下各个子序列的和,最后找到和最大的子序列。
5、 找出最长不包含重复字符的子串
比如:字符串”aaaaa”, 最长无重复字符的子串是”a”,长度为1;
又如:“abababcmdefghikjflababaefabcdezghikjfaefew”,有四个长度都为12(最长)符合条件的子串:abcmdefghikj、fabcdezghikj、abcdezghikjf和bcdezghikjfa。
分析:对于字符串中第i位的字符,如果它知道以第i-1位字符
结尾
的无重子串的长度L[i-1],又知道第i位字符的前一个出现位置k,于是就可以得出以第i位字符作结尾的无重子串的长度:L[i] = min(L[i-1]+1, i-k),初始L[0] = 1,于是可以得到一个O(n)的算法,打印所有符合条件的子串时,只需要遍历L数组一边,如果L[i]=max,则打印以i结尾的max长子串。至于空间的话,因为要建个256的数组保存第i位字符的前一个出现位置k,第i位符找对应的数组值,如果该值是初始值,刚该字符第一次出现,如果该值已经被赋过值,则该字符上一次出现的位置就是这个值。所以空间是常数。