最长公共子序列

来源:互联网 发布:电脑屏幕竖屏 程序员 编辑:程序博客网 时间:2024/05/16 09:05

最长公共子序列,英文缩写为LCS(Longest Common Subsequence)。其定义是,一个序列 S ,如果分别是两个或多个已知序列的子序列,且是所有符合此条件序列中最长的,则 S 称为已知序列的最长公共子序列。而最长公共子串(要求连续)和最长公共子序列是不同的。
动态规划的一个计算两个序列的最长公共子序列的方法如下:
以两个序列 X、Y 为例子:
设有二维数组f[i,j] 表示 X 的 i 位和 Y 的 j 位之前的最长公共子序列的长度,则有:
f[1][1] = same(1,1);
f[i,j] = max{f[i-1][j -1] + same(i,j),f[i-1,j],f[i,j-1]}
其中,same(a,b)当 X 的第 a 位与 Y 的第 b 位相同时为“1”,否则为“0”。
此时,二维数组中最大的数便是 X 和 Y 的最长公共子序列的长度,依据该数组回溯,便可找出最长公共子序列。
该算法的空间、时间复杂度均为O(n^2)
面试题目如下:
删除最少字符 使字符串成为回文串。
给定一个字符串s,你可以从中删除一些字符,使得剩下的串是一个回文串。如何删除才能使得回文串最长呢?输出需要删除的字符个数。
对于这题来说,插入字符和删除字符使其成为回文串,答案是一样的.
首先求s的反串rs,然后对s和rs求最长公共子序列,要删除的字符个数就是LCS.
时间复杂度: O(N^2)

#include <bits/stdc++.h>using namespace std;const int MAXN=1010;int dp[MAXN][MAXN];class Solution{public:   int solve(string &s)   {       return s.length()-getLCS(s);   }   int getLCS(string &s1)   {       string s2(s1);       reverse(s2.begin(),s2.end());       int len=s1.length();       memset(dp,0,sizeof dp);       for(int i=0;i<len;++i)       {           for(int j=0;j<len;++j)           {               if(s1[i]==s2[j])                   dp[i+1][j+1]=dp[i][j]+1;               else dp[i+1][j+1]=max(dp[i][j+1],dp[i+1][j]);           }       }       return dp[len][len];   }};int main(){   string s;   while(cin>>s)   {       Solution solution;       cout<<solution.solve(s)<<endl;   }   return 0;}
0 0
原创粉丝点击