UVA 11404 Palindromic Subsequence

题意:给你一个字符串, 求最长的回文子序列, 若答案不唯一, 则输出字典序最小的

分析:

 解法1 :

区间dp, dp[i][j]表示字符串s[i]到s[j]构成回文子序列学删除的最小字符数, 

dp[i][j] 字符串s[i]到s[j]构成回文子序列许删除的最少字符数
path[i][j] 字符串s[i]到s[j]可构成的最长回文子序列

#include 
   
   
    
    
#include 
    
    
     
     
#include 
     
     
      
      
#include 
      
      
       
       
#include 
       
       
         using namespace std; string path[1010][1010]; int dp[1010][1010]; char s[1010]; int main() { while(scanf("%s", s + 1) == 1) { int n = strlen(s + 1); for(int i=n; i>=1; i--) for(int j=i; j<=n; j++) { if(s[i] == s[j]) { if(i == j) { dp[i][j] = 0; path[i][j] = s[i]; } else { dp[i][j] = dp[i+1][j-1]; path[i][j] = s[i] + path[i+1][j-1] + s[j]; } } else if(dp[i+1][j] > dp[i][j-1]) { dp[i][j] = dp[i][j-1] + 1; path[i][j] = path[i][j-1]; } else if(dp[i][j-1] > dp[i+1][j]) { dp[i][j] = dp[i+1][j] + 1; path[i][j] = path[i+1][j]; } else { dp[i][j] = dp[i+1][j] + 1; path[i][j] = min(path[i][j-1], path[i+1][j]); } } cout << path[1][n] << endl; } return 0; } 
       
      
      
     
     
    
    
   
   

解法2:

转化为lcs, 用结构体进行保存,一维只长度, 一维指构成的字符串

#include 
   
   
    
    
#include 
    
    
     
     
#include 
     
     
      
      
#include 
      
      
       
       
#include 
       
       
         using namespace std; struct node { int len; string str; }dp[1010][1010]; char s1[1010], s2[1010]; int main() { while(scanf("%s", s1+1) == 1) { int n = strlen(s1 + 1); strcpy(s2+1, s1+1); reverse(s2+1, s2+1+n); for(int i=0; i<=n; i++) for(int j=0; j<=n; j++) { dp[i][j].len = 0; dp[i][j].str = ""; } for(int i=1; i<=n; i++) for(int j=1; j<=n; j++) { if(s1[i] == s2[j]) { dp[i][j].len = dp[i-1][j-1].len + 1; dp[i][j].str = dp[i-1][j-1].str + s1[i]; } else if(dp[i-1][j].len > dp[i][j-1].len) { dp[i][j].len = dp[i-1][j].len; dp[i][j].str = dp[i-1][j].str; } else if(dp[i][j-1].len > dp[i-1][j].len) { dp[i][j].len = dp[i][j-1].len; dp[i][j].str = dp[i][j-1].str; } else { dp[i][j].len = dp[i-1][j].len; dp[i][j].str = min(dp[i][j-1].str, dp[i-1][j].str); } } string s = dp[n][n].str; int l = dp[n][n].len; if(l & 1) { for(int i=0; i<(l-1)/2; i++) cout << s[i]; for(int i=(l-1)/2; i>=0; i--) cout << s[i]; } else { for(int i=0; i 
        
          =0; i--) cout << s[i]; } cout << endl; } return 0; } 
         
       
      
      
     
     
    
    
   
   

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值