WordStack
https://ac.nowcoder.com/acm/problem/107414
这个题一定要好好读题,尤其是对于与上一个字符串对比的得分是怎么计算的,不是连续子串相同,不是最大公共子序列,而是对齐情况下,最大相同的字符个数。题目中的示例正好避开了这个说明,导致思路错误。
链接:https://ac.nowcoder.com/acm/problem/107414
来源:牛客网
padding them with leading spaces to maximize the number of non-space characters that are the same as the character immediately above them on the preceding line.
好好注意上面的一句话,是说,可以增加空格,使上下的字符串对齐,得分是上下相同的字符个数,上面加粗的是单数,不是复数,并且牛客上面这个题的注释是错误的,也使我们产生了误解。这道题原题来自北京大学ACM题库,如下
http://poj.org/problem?id=2817
北京大学网站上的示例是这样的
而牛客上是这样的
很明显cde的一行少移了一位,导致我们对题目理解出错。
上面是唯一一个题解,在字符串是10的时候,结果是错误的,这个题解在北大的网站上也是通过的,但是题目中明确说明了每个单词长度从1-10,包含10(如果我没理解错的话),如下:
链接:https://ac.nowcoder.com/acm/problem/107414
来源:牛客网
Each word will be made up of the characters 'a' to 'z' and will be between 1 and 10 characters long (inclusive).
也就是牛客和北大网站上的case都没覆盖边界情况。
理解了这道题,那么思路就是,首先创建一个表,用来保存每两个单词之间相同的字符个数,也就是得分数,然后呢,就是找到一个排序,让每个单词与上一个之间得分总数最大。
这道题整体的思路就是dp,创建单词间的得分可以dp,计算单词如何排序而达到最大值也可以dp。这里计算得分的时候使用的dp,因为分配的空间少一些,计算排序的话,用的穷举法,因为就是排列,最多10个的话,总的计算量不算大,如果用dp,思路有点绕,没有想通这种方法,代码如下:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<set>
#include<climits>
using namespace std;
char INPUT_STR[11][11] = { 0 };
int DP[11][11] = { 0 };
int MAX_SCORE = 0;
int MAX_SOCRE_STR_SORT[10] = { 0 };
int INPUT_NUM = 0;
void swap(int &a, int &b)
{
int temp = a;
a = b;
b = temp;
}
void perm(int arrindex[], int low, int high)
{
if (low == high)
{
int tmpmaxn = 0;
for (int i = 1; i < INPUT_NUM; i++)
{
tmpmaxn += DP[arrindex[i]][arrindex[i - 1]];
}
if (tmpmaxn > MAX_SCORE)
{
MAX_SCORE = tmpmaxn;
for (int i = 0; i < INPUT_NUM; i++)
{
MAX_SOCRE_STR_SORT[i] = arrindex[i];
}
}
}
else
{
for (int i = low; i <= high; i++)
{
swap(arrindex[i], arrindex[low]);
perm(arrindex, low + 1, high);
swap(arrindex[i], arrindex[low]);
}
}
}
int get_max_lcs(char *stra, char *strb)
{
int LCS_DP[10][10] = { 0 };
int slena = strlen(stra);
int slenb = strlen(strb);
int maxnum = 0;
for (int i = 0; i < slena; i++)
{
for (int j = 0; j < slenb; j++)
{
int pren = 0;
if (i > 0 && j > 0)
{
pren = LCS_DP[i - 1][j - 1];
}
if (stra[i] == strb[j])
{
LCS_DP[i][j] = pren + 1;
}
else
{
LCS_DP[i][j] = pren;
}
if (LCS_DP[i][j] > maxnum)
{
maxnum = LCS_DP[i][j];
}
}
}
return maxnum;
}
int main()
{
while (cin >> INPUT_NUM && INPUT_NUM > 0)
{
MAX_SCORE = 0;
memset(MAX_SOCRE_STR_SORT, 0, 10 * sizeof(int));
memset(DP, 0, 10 * sizeof(int));
memset(INPUT_STR, 0, 10 * sizeof(char));
int* arrindex = new int[INPUT_NUM];
for (int i = 0; i < INPUT_NUM; i++)
{
cin >> INPUT_STR[i];
*(arrindex + i) = i;
}
for (int i = 0; i < INPUT_NUM; i++)
{
for (int j = i + 1; j < INPUT_NUM; j++)
{
DP[i][j] = get_max_lcs(INPUT_STR[i], INPUT_STR[j]);
DP[j][i] = DP[i][j];
}
}
perm(arrindex, 0, INPUT_NUM - 1);
delete[] arrindex;
cout << MAX_SCORE << endl;
}
}