zoukankan      html  css  js  c++  java
  • UVA 11404 Plalidromic Subsquence (回文子序列,LCS)

    最长回文子序列可以用求解原串s和反转串rv的LCS来得到,因为要求回文串分奇偶,dp[i][j]保存长度,

    要求字典序最小,dp[i][j]应该表示回文子序列的端点,所以边界为单个字符,即i+j=len+1。

    这题最麻烦的地方在于字典序,我是写了个比较函数,有点暴力(常数大)。

    也可以反着定义,这时结点就要保存那个状态的字符串了(这样定义比较字典序的时候常数小)

    #include<bits/stdc++.h>
    using namespace std;
    
    #define MP make_pair
    #define fi first
    #define se second
    
    const int LEN = 1e3+5;
    char s[LEN],rv[LEN];
    int dp[LEN][LEN];
    pair<int,int> pre[LEN][LEN];
    char val[LEN][LEN];
    
    inline void updata(int i,int j,int v,char c,const pair<int,int> &prv)
    {
        dp[i][j] = v;
        pre[i][j] = prv;
        val[i][j] = c;
    }
    
    const auto nil = MP(0,0);
    
    #define dim(x) [x.fi][x.se]
    bool cmpLex(pair<int,int> a,pair<int,int> b)
    {
        //
        while(a != nil && val[a.fi][a.se] == val[b.fi][b.se]){
            a = pre dim(a); b = pre dim(b);
        }
        return val dim(a) < val dim(b);
    }
    
    //#define LOCAL
    int main()
    {
    #ifdef LOCAL
        freopen("in.txt","r",stdin);
    #endif
    
        while(gets(s)){
            int len = strlen(s);
            for(int i = 0; i < len; i++){
                rv[len-1-i] = s[i];
            }
            int hd1,hd2,vl = 0;
            for(int i = 1; i <= len; i++){
                int j = len+1-i;
                dp[i][j] = 1; val[i][j] = s[i-1]; pre[i][j] = nil;
                if(dp[i][j] > vl || ( dp[i][j] == vl && cmpLex( MP(i,j), MP(hd1,hd2) ) ) ){//
                    vl = dp[i][j];
                    hd1 = i; hd2 = j;
                }
                for(int k = 1; k < j; k++) dp[i][k] = 0;
                for(j++; j <= len; j++){
                    if(s[i-1] == rv[j-1]){
                        updata(i,j,dp[i-1][j-1]+2,s[i-1],make_pair(i-1,j-1));
                        if(dp[i][j] > vl || (dp[i][j] == vl && cmpLex(MP(i,j),MP(hd1,hd2)) ) ){//
                            vl = dp[i][j];
                            hd1 = i; hd2 = j;
                        }
                    }else {
                        if(dp[i-1][j] > dp[i][j-1] || (dp[i-1][j] == dp[i][j-1] && cmpLex(MP(i-1,j),MP(i,j-1)) ) ){//
                            updata(i,j,dp[i-1][j],val[i-1][j],pre[i-1][j]);
                        }else {
                            updata(i,j,dp[i][j-1],val[i][j-1],pre[i][j-1]);
                        }
                    }
    
                }
            }
            int pv = (vl+1)>>1,ln = vl;
    
            auto u = MP(hd1,hd2);
            for(int i = 0; i < pv; i++){
                s[i] = val[u.fi][u.se];
                u = pre[u.fi][u.se];
            }
    
            s[ln] = '';
            for(int i = pv; i < ln; i++){
                s[i] = s[ln-1-i];
            }
            puts(s);
        }
        return 0;
    }
  • 相关阅读:
    语音识别系列之区分性训练和LF-MMI【转】
    node、npm安装与升级
    Vue3.0 新特性以及使用经验总结
    div垂直居中的方法
    前端性能优化
    大型网站设计总结
    前端SEO
    前端埋点总结
    jenkins自动构建、自动部署
    Python常见whl文件集合
  • 原文地址:https://www.cnblogs.com/jerryRey/p/4851673.html
Copyright © 2011-2022 走看看