最大公共子序列(删除字符使得剩下的是回文串)

来源:互联网 发布:中国酒类行业产量数据 编辑:程序博客网 时间:2024/06/11 14:46
给定一个字符串s,你可以从中删除一些字符,使得剩下的串是一个回文串。如何删除才能使得回文串最长呢?

输出需要删除的字符个数。


思路:采用常规方法复杂度太大,应该采用动态规划的思想。求原字符串和其反串的最大公共子序列(不是子串,因为可以不连续)的长度(使用动态规划),然后用原字符串的长度减去这个最大公共子串的长度就得到了最小删除的字符个数。

状态:当str1的下标为m,str2的下标是n的时候(不考虑后面的),此时的最长子序列长度L。

转移方程:1,如果str1(m)==str2(n),那么L(m,n)=L(m-1,n-1)+1。2,如果str1(m)!=str2(n),那么L(m,n)=max(L(m-1,n),L(m,n-1))

假如m和n相等,那么这个时候最大子序列无疑是前一个L(m-1,n-1)加上1,因为这两个字符串这个地方的字符都可以加入到最长子序列里面去。如果不相等,那么要么舍弃新来的来自str1的那个字符m号,要么舍弃str2的n号字符(最长子序列每个位置上当然都是唯一确定的一个字符),舍弃之后,就从

L(m-1,n),L(m,n-1)当中挑一个更长的为当前状态的最长子序列。

<pre name="code" class="cpp">#include <iostream>#include <algorithm>#include <string>using namespace std; int getLCS(string &s1){    string s2(s1);    reverse(s2.begin(),s2.end());    const int len=s1.length();    int dp[1000][1000]={0};    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 len-dp[len][len];} int main(){   string s;   while(cin>>s)       cout<<getLCS(s)<<endl;   return 0;}



0 0
原创粉丝点击