C++ 从给定的一组数中求回文序列的个数
假设我们得到一组数字,比如20 40 20 60 80 60 它可以分为两个回文序列:C++ 从给定的一组数中求回文序列的个数,c++,algorithm,palindrome,C++,Algorithm,Palindrome,假设我们得到一组数字,比如20 40 20 60 80 60 它可以分为两个回文序列:204020,和608060。 它也可以分成6个回文序列,每个序列包含一个数字 如何从C++中给定的一组数字中找到最小回文序列的数量? 这不是我的家庭作业。真正的问题。一个简单的方法是首先查看每个O(n3)子序列,并检查它是否是回文。一旦我们知道哪些子序列是回文序列,我们就可以在O(n2)时间内进行动态规划,以找到覆盖整个序列的最小数量的连续子序列 对于输入 20 40 20 20 80 60 < /COD>,
204020
,和608060
。
它也可以分成6个回文序列,每个序列包含一个数字
如何从C++中给定的一组数字中找到最小回文序列的数量?
这不是我的家庭作业。真正的问题。一个简单的方法是首先查看每个O(n3)子序列,并检查它是否是回文。一旦我们知道哪些子序列是回文序列,我们就可以在O(n2)时间内进行动态规划,以找到覆盖整个序列的最小数量的连续子序列
对于输入<代码> 20 40 20 20 80 60 < /COD>,C++实现以下打印<代码> [20 40 20 ] [60 80 60 ] < /代码> .<
#include <cstdio>
#include <vector>
using namespace std;
int main() {
// Read the data from standard input.
vector<int> data;
int x;
while (scanf("%d", &x) != EOF) {
data.push_back(x);
}
int n = data.size();
// Look at every subsequence and determine if it's a palindrome.
vector<vector<bool> > is_palindrome(n);
for (int i = 0; i < n; ++i) {
is_palindrome[i] = vector<bool>(n);
for (int j = i; j < n; ++j) {
bool okay = true;
for (int left = i, right = j; left < right; ++left, --right) {
if (data[left] != data[right]) {
okay = false;
break;
}
}
is_palindrome[i][j] = okay;
}
}
// Dynamic programming to find the minimal number of subsequences.
vector<pair<int,int> > best(n);
for (int i = 0; i < n; ++i) {
// Check for the easy case consisting of one subsequence.
if (is_palindrome[0][i]) {
best[i] = make_pair(1, -1);
continue;
}
// Otherwise, make an initial guess from the last computed value.
best[i] = make_pair(best[i-1].first + 1, i-1);
// Look at earlier values to see if we can improve our guess.
for (int j = i-2; j >= 0; --j) {
if (is_palindrome[j+1][i]) {
if (best[j].first + 1 < best[i].first) {
best[i].first = best[j].first + 1;
best[i].second = j;
}
}
}
}
printf("Minimal partition: %d sequences\n", best[n-1].first);
vector<int> indices;
int pos = n-1;
while (pos >= 0) {
indices.push_back(pos);
pos = best[pos].second;
}
pos = 0;
while (!indices.empty()) {
printf("[%d", data[pos]);
for (int i = pos+1; i <= indices.back(); ++i) {
printf(" %d", data[i]);
}
printf("] ");
pos = indices.back()+1;
indices.pop_back();
}
printf("\n");
return 0;
}
#包括
#包括
使用名称空间std;
int main(){
//从标准输入读取数据。
矢量数据;
int x;
while(scanf(“%d”,&x)!=EOF){
数据。推回(x);
}
int n=data.size();
//查看每个子序列并确定它是否是回文。
向量为_回文(n);
对于(int i=0;i=0;--j){
if(是回文[j+1][i]){
if(最佳[j].first+1<最佳[i].first){
最佳[i]。第一=最佳[j]。第一+1;
最佳[i]。第二个=j;
}
}
}
}
printf(“最小分区:%d个序列\n”,最佳[n-1]。第一);
向量指数;
int pos=n-1;
而(位置>=0){
指数。推回(pos);
pos=最佳[pos]。第二;
}
pos=0;
而(!index.empty()){
printf(“[%d”,数据[pos]);
对于(int i=pos+1;i一种简单的方法是首先查看每个O(n3)子序列并检查它是否是回文序列。一旦我们知道哪些子序列是回文序列,我们就可以在O(n2)时间内进行动态规划,以找到覆盖整个序列的最小数量的连续子序列
对于输入<代码> 20 40 20 20 80 60 < /COD>,C++实现以下打印<代码> [20 40 20 ] [60 80 60 ] < /代码> .<
#include <cstdio>
#include <vector>
using namespace std;
int main() {
// Read the data from standard input.
vector<int> data;
int x;
while (scanf("%d", &x) != EOF) {
data.push_back(x);
}
int n = data.size();
// Look at every subsequence and determine if it's a palindrome.
vector<vector<bool> > is_palindrome(n);
for (int i = 0; i < n; ++i) {
is_palindrome[i] = vector<bool>(n);
for (int j = i; j < n; ++j) {
bool okay = true;
for (int left = i, right = j; left < right; ++left, --right) {
if (data[left] != data[right]) {
okay = false;
break;
}
}
is_palindrome[i][j] = okay;
}
}
// Dynamic programming to find the minimal number of subsequences.
vector<pair<int,int> > best(n);
for (int i = 0; i < n; ++i) {
// Check for the easy case consisting of one subsequence.
if (is_palindrome[0][i]) {
best[i] = make_pair(1, -1);
continue;
}
// Otherwise, make an initial guess from the last computed value.
best[i] = make_pair(best[i-1].first + 1, i-1);
// Look at earlier values to see if we can improve our guess.
for (int j = i-2; j >= 0; --j) {
if (is_palindrome[j+1][i]) {
if (best[j].first + 1 < best[i].first) {
best[i].first = best[j].first + 1;
best[i].second = j;
}
}
}
}
printf("Minimal partition: %d sequences\n", best[n-1].first);
vector<int> indices;
int pos = n-1;
while (pos >= 0) {
indices.push_back(pos);
pos = best[pos].second;
}
pos = 0;
while (!indices.empty()) {
printf("[%d", data[pos]);
for (int i = pos+1; i <= indices.back(); ++i) {
printf(" %d", data[i]);
}
printf("] ");
pos = indices.back()+1;
indices.pop_back();
}
printf("\n");
return 0;
}
#包括
#包括
使用名称空间std;
int main(){
//从标准输入读取数据。
矢量数据;
int x;
while(scanf(“%d”,&x)!=EOF){
数据。推回(x);
}
int n=data.size();
//查看每个子序列并确定它是否是回文。
向量为_回文(n);
对于(int i=0;i=0;--j){
if(是回文[j+1][i]){
if(最佳[j].first+1<最佳[i].first){
最佳[i]。第一=最佳[j]。第一+1;
最佳[i]。第二个=j;
}
}
}
}
printf(“最小分区:%d个序列\n”,最佳[n-1]。第一);
向量指数;
int pos=n-1;
而(位置>=0){
指数。推回(pos);
pos=最佳[pos]。第二;
}
pos=0;
而(!index.empty()){
printf(“[%d”,数据[pos]);
对于(int i=pos+1;我请告诉我们你做了什么,至少是你头脑中的一些想法。@aga_pan我想找到一个特定数字的重复次数,并找到所有可能的回文。但现在我不知道该怎么做。@yash.cr7:在你上面给出的示例中,你键入的20 40 80
正确吗是不是应该是20 40 20 60 80 60
?我想知道你是在寻找严格连续的子序列,还是也允许非连续的子序列。@MichaelLaszlo对不起,我错了。我编辑了我的问题。它们应该是连续的。非常好,谢谢。你现在有足够的声誉来支持upvot顺便说一句,e答案。请告诉我们你做了什么,至少你脑子里有一些想法。@aga_pan我想找到一个特定数字的重复次数并找到所有可能的回文。但现在我不知道怎么做。@yash.cr7:在你上面给出的例子中,你键入的20 40 80
正确吗,还是应该是2040608060
?我想知道你是在寻找严格连续的子序列,还是也允许非连续的子序列。@MichaelLaszlo对不起,我错了。我编辑了我的问题。它们应该是连续的。非常好,谢谢。你现在已经有足够的声誉来支持你了顺便说一句,我认为这不是答案