大意:一台机器可以使用2种命令,即复制最后一个单词,将最后一个单词的最后一个字母删去,问你使用最少打印的字母打印所有的字符串。
思路:每次枚举出于前一个字符串具有最长长度的公共前缀,贪心性质可以被证明,直到所有的字符串都被包括。
CODE:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
using namespace std;
#define MAXN 1001
char str[MAXN][MAXN];
int save[MAXN], n;
void solve()
{
bool vis[MAXN] = {0};
int tmp;
int cur = 0, tot = 1, ans = strlen(str[0]);
save[0] = 0;
for(int i = 1; i < n; i++)
{
int max = -1;
vis[cur] = 1;
for(int j = 0; j < n; j++) if(!vis[j])
{
int k;
for(k = 0; k < strlen(str[cur]) && k < strlen(str[j]); k++)
{
if(str[cur][k] != str[j][k]) break;
}
if(max < k)
{
max = k;
tmp = j;
}
}
save[tot++] = cur = tmp;
ans += strlen(str[cur]) - max;
}
printf("%d\n", ans);
for(int i = 0; i < tot; i++)
{
printf("%s\n", str[save[i]]);
}
}
int main()
{
int T;
scanf("%d%*c", &T);
while(T--)
{
scanf("%d", &n);
for(int i = 0; i < n; i++)
scanf("%s", str[i]);
solve();
}
return 0;
}
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
using namespace std;
#define MAXN 1001
char str[MAXN][MAXN];
int save[MAXN], n;
void solve()
{
bool vis[MAXN] = {0};
int tmp;
int cur = 0, tot = 1, ans = strlen(str[0]);
save[0] = 0;
for(int i = 1; i < n; i++)
{
int max = -1;
vis[cur] = 1;
for(int j = 0; j < n; j++) if(!vis[j])
{
int k;
for(k = 0; k < strlen(str[cur]) && k < strlen(str[j]); k++)
{
if(str[cur][k] != str[j][k]) break;
}
if(max < k)
{
max = k;
tmp = j;
}
}
save[tot++] = cur = tmp;
ans += strlen(str[cur]) - max;
}
printf("%d\n", ans);
for(int i = 0; i < tot; i++)
{
printf("%s\n", str[save[i]]);
}
}
int main()
{
int T;
scanf("%d%*c", &T);
while(T--)
{
scanf("%d", &n);
for(int i = 0; i < n; i++)
scanf("%s", str[i]);
solve();
}
return 0;
}