求解最长公共子序列问题(LCS)

来源:互联网 发布:js访问frame 编辑:程序博客网 时间:2024/06/07 15:41

刷leetcode一直没做到大名鼎鼎的LCS问题,也不明白LCS具体是什么问题,直到做到去年腾讯笔试的一道编程题:


给定一个字符串s,你可以从中删除一些字符,使得剩下的串是一个回文串。如何删除才能使得回文串最长呢?
输出需要删除的字符个数。

输入描述:

输入数据有多组,每组包含一个字符串s,且保证:1<=s.length<=1000.



输出描述:

对于每组数据,输出一个整数,代表最少需要删除的字符个数。


输入例子:
abcdagoogle

输出例子:
2

2



最初毫无头绪,还想着能不能通过思考解最长回文串的解法来解答,后来实在无果,借鉴网上的解答,发现可以使用字符串反转然后求LCS问题来轻松解答。于是写下这篇博文,也算是为自己了了LCS问题这个坑。

"

什么是最长公共子序列呢?举个简单的例子吧,一个数列S,若分别是两个或多个已知序列的子序列,且是所有符合条件序列中最长的,则S称为已知序列的最长公共子序列。

  举例如下,如:有两个随机数列,1 2 3 4 5 6 和 3 4 5 8 9,则它们的最长公共子序列便是:3 4 5。

  一直不明白:最长公共子串和最长公共子序列的区别。
  
   上网查了下,最长公共子串(Longest Common Substirng)和最长公共子序列(Longest Common Subsequence,LCS)的区别为:子串是串的一个连续的部分,子序列则是从不改变序列的顺序,而从序列中去掉任意的元素而获得新的序列;也就是说,子串中字符的位置必须是连续的,子序列则可以不必连续。
"


这是我最初不能理解LCS的主要原因,我还把他当作字符串问题来解决。

这道题可以通过动态规划来做。


首先初始化一个二维数组lcs[][],各元素均为0;

现在对这个数组进行状态及递推的判断,i,j分别从0开始,双层循环。

如果str1[i]==str[j]则lcs[i][j]=lcs[i-1][j-1]+1;

如果str1[i]!=str[j],那么lcs[i][j]=max(lcs[i][j-1],lcs[i-1][j])   /*这句话必须理解,这是算法的关键,可以结果棋盘图去思考


有了这个递推关系,解答就很简单了·~~~~

0 0
原创粉丝点击