将一组元素分解成最少数量的回文

Breaking an array of elements into least number of palindromes

本文关键字:回文 分解 元素 一组      更新时间:2023-10-16

你会如何解决这样一个问题:

一个给定的整数序列可以被分解成如下的部分每一个都是回文。考虑序列34,45,34,56,34。这可以分成3个回文序列,分别是34,45,34构成第一,56构成第二,34构成第三层。它也可以被分解成5个回文序列包含单个数字的。因此,可能有许多不同的方法来将给定的序列分解为回文序列。我们想要确定最小的数C,使得给定的数列可以是分解成C回文序列。

我的解决方案是这样做的:找到数组的最大回文(最大长度的回文),取数组中除了这个最大回文之外的其余部分,并尝试找到它的最大回文,以此类推,同时增加回文的数量。

这是我目前为止写的:

#include <algorithm>
#include <iostream>
#include <vector>
#define print(arr) for(auto pos = arr.begin(); pos != arr.end(); ++pos) cout << *pos << " "; cout << endl;
typedef long long int ll;
using namespace std;
int calc(vector<ll> A, int N) {
    int i = N;
    vector <ll> t1, t2;
    while (i >= 0) {
        t1 = vector <ll> (A.begin(), A.begin()+i);
        t2 = vector <ll> (t1.rbegin(), t1.rend());
        if (t1 == t2) return i;
        i--;
    }
    return 0;
}
int main() {
    int N;
    ll x;
    cin >> N;
    vector <ll> A(N);
    for (int i = 0; i < N; i++) {
        cin >> x;
        A[i] = x;
    }
    int temp = calc(A,N);
    int c = 0;
    while (temp != 0) {
        A = vector <ll> (A.begin()+temp, A.end());
        N = (int)A.size();
        temp = calc(A, N);
        c++;
    }
    cout << c << endl;
}

然而,我得到了3个错误的测试用例。后来意识到,我的程序在测试用例中输出4而不是2:N=8,{2,1,2,1,2,3,2,1}。它需要回文为{2,1,1,2,2},{3},{2},{1},而它应该是{2,1,2},{1,2,3,2,1}。如果我反转向量并计算两者之间的最小答案,我将得到这个测试用例的正确答案2,但对于Codechef上的其他人,我仍然得到2个错误的测试用例,可能出于与我得到这个错误相同的原因。

不管怎样,你知道我该如何改进吗?

codechef上的问题链接:https://www.codechef.com/ZCOPRAC/problems/ZCO15001这是一个正在进行的比赛,但该比赛只是在印度举行的区域计算奥林匹克竞赛的练习比赛。

这是动态规划的一个典型问题。您可以通过O(N ^ 2)复杂度轻松解决这个问题,其中N是输入字符串的大小。

首先,您可以预先计算O(N ^ 2)复杂度的所有回文,以回答O(1)[i, j]子串是否为回文(让它成为您的练习)。

然后可以计算数组dp,其中dp[i]是子字符串[0, i]的答案。要找到dp[i],您需要做:dp[i] = min(dp[i], dp[j] + 1)为所有j,其中j < i和子字符串[j + 1, i]是回文。在这里,您使用回文预计算来检查O(1)中的子字符串[j + 1, i]是否回文。dp[0]当然是1

答案是dp[N - 1]

注: