大意:一台机器可以使用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;
}