Mnemonics and Palindromes URAL - 1635 区间DP

题意:   在串中划分出最少个数的回文串。输出最少回文串的个数,并将回文串输出。

think:    首先肯定是区间问题。

             还是没自己解决这个问题看了题解。 

             dp[i]表示以i结束最少的回文串的个数。

             枚举区间预处理出该区间是否为字符串,

             然后如果区间j~i是回文串的话,  那么转移方程则为 dp[i] = min(dp[j-1]+1, dp[i])[然后还要记录路径,这里就和bfs记  录          路径差不多]。


#include <bits/stdc++.h>
#define ll long long
#define ms(x) memset(x, 0, sizeof(x))
#define inf 0x3f3f3f3f
#define mf(x) memset(x, inf, sizeof(x))
using namespace std;
const int N = 4123;
int dp[N], pre[N];
bool isPa[N][N];
char s[4123];
vector<int>q;
int main() {
    while(scanf("%s", s+1) != EOF) {
        int len = strlen(s+1);
        ms(isPa); ms(pre);
        q.clear();
        for(int i=1;i<=len;i++){
            isPa[i][i] = 1;
            int l = i, r = i;
            while(l>=1 && r<=len && s[l] == s[r]){
                isPa[l][r] = 1;
                l--, r++;
            }
            l = i, r = i+1;
            while(l>=1 && r<=len && s[l] == s[r]){
                isPa[l][r] = 1;
                l--, r++;
            }
        }
        mf(dp);
        dp[0] = 0;
        pre[1] = 0;
        for(int i=1;i<=len;i++){
            for(int j=i;j>=1;j--){
                if(isPa[j][i]){
                    if(dp[i]>(dp[j-1] + 1)){
                        dp[i] = dp[j-1] + 1;
                        pre[i] = j-1;
                    }
                }
            }
        }
        printf("%d\n", dp[len]);
        int tp = pre[len];
        q.push_back(len);
        while(tp!=0){
            q.push_back(tp);
            tp = pre[tp];
        }
        q.push_back(0);
        for(int i=q.size()-1; i>=1; i--){
            if(i!=q.size()-1) printf(" ");
            for(int l = q[i]+1; l<=q[i-1]; l++){
                printf("%c", s[l]);
            }
        }
        printf("\n");
    }
    return 0;
}



猜你喜欢

转载自blog.csdn.net/khn64/article/details/80570032
今日推荐