UVA 502 - DEL command(贪心构造)

 DEL command 

It is required to find out whether it is possible to delete given files from MS-DOS directory executing the DEL command of MS-DOS operation system only once. There are no nested subdirectories.

A note 

DEL command has the following format: DEL wildcard


The actual wildcard as well as a full file name can be made up either of a name containing 1 up to 8 characters or of a name and extension, containing up to 3 characters. The point character ``." separates the extension from the file name. The extension can be empty and this is equivalent to a name without any extension (in this case a wildcard ends with a point). In a wildcard the characters ``?" and ``*" can be used. A question mark substitutes exactly one character of the full file name excluding a point, an asterisk any sequence of characters (containing no points) even empty one. An asterisk can appear only at the last position of the name and the extension.


MS-DOS system can permit maybe other wildcards but they can not be used in this task. File names and extensions consist only of Latin capitals and digits.

Input 

The first line of the input is an integer M, then a blank line followed by M datasets. There is a blank line between datasets.

Input data for each dataset contains a list of full file names without empty lines and spaces. Each name is written in a separate line of input data file and preceded with a control sign: ``-" for delete or ``+" for keep. Full file names are not repeated. The list comprises at least one file, and at least one file is marked to be deleted. There are no more than 1000 files.

Output 

For each dataset, write to the first line of output the required DEL command (only one proposal) or IMPOSSIBLE  if there is no solution. A space should separate `` DEL " from wildcard. Print a blank line between datasets.

Sample Input 

1

-BP.EXE
-BPC.EXE
+TURBO.EXE

Possible output 

DEL ?P*.*

题意:构造一条指令,删除-的文件,不删除+的文件,?代表任意字符,*代表任意个数字符,*只能加在末尾。

思路:贪心,把要删除和保留的分开保存,然后对于要删除的每一个字母,如果全相同,就用这个字母,如果有不同,就用?,如果长短不一,末尾就用*填,然后在用构造出来的串去和保留的一一判断,如果有一个保留会被删除,就是错的。

代码:

#include <stdio.h>
#include <string.h>

const int N = 1005;

int t, n[2], sn, sn1;
char str[15], str1[15];
struct F {
	char a[15], b[15];
} f[2][N];

void tra() {
	int s;
	if (str[0] == '-') s = 0;
	else s = 1;
	int i = 1, len = strlen(str), an = 0, bn = 0;
	for (; str[i] != '.' && i < len; i++)
		f[s][n[s]].a[an++] = str[i];
	for (i = i + 1; i < len; i++)
		f[s][n[s]].b[bn++] = str[i];
	n[s]++;
}

int judge(int i) {
	char c = f[0][0].a[i];
	for (int j = 0; j < n[0]; j++) {
		if (f[0][j].a[i] != c) {
			if (f[0][j].a[i] == '\0' || c == '\0') return -1;
			return 0;
		}
	}
	return 1;
}

int judge1(int i) {
	char c = f[0][0].b[i];
	for (int j = 0; j < n[0]; j++) {
		if (f[0][j].b[i] != c) {
			if (f[0][j].b[i] == '\0' || c == '\0') return -1;
			return 0;
		}
	}
	return 1;
}

bool ok1(int i) {
	int len = strlen(str);
	if (str[len - 1] == '*') len--;
	else if (len < strlen(f[1][i].a)) return false;
	for (int j = 0; j < len; j++) {
		if (str[j] != '\0' && f[1][i].a[j] == '\0') return false;
		if (str[j] != '?' && str[j] != f[1][i].a[j]) return false;
	}
	return true;
}

bool ok2(int i) {
	int len = strlen(str1);
	if (str1[len - 1] == '*') len--;
	else if (len < strlen(f[1][i].b)) return false;
	for (int j = 0; j < len; j++) {
		if (str1[j] != '\0' && f[1][i].b[j] == '\0') return false;
		if (str1[j] != '?' && str1[j] != f[1][i].b[j]) return false;
	}
	return true;
}

bool OK(int i) {
	if (ok1(i) && ok2(i)) return true;
	return false;
}

void make() {
	sn = 0; sn1 = 0; int i;
	memset(str, 0, sizeof(str));
	memset(str1, 0, sizeof(str1));
	for (i = 0; ; i++) {
		if (judge(i) == 1) {
			if (f[0][0].a[i] == '\0') break;
			str[sn++] = f[0][0].a[i];
		}
		else if (judge(i) == -1) {
			str[sn++] = '*';
			break;
		}
		else str[sn++] = '?';
	}
	for (i = 0; ; i++) {
		if (judge1(i) == 1) {
			if (f[0][0].b[i] == '\0') break;
			str1[sn1++] = f[0][0].b[i];
		}
		else if (judge1(i) == -1) {
			str1[sn1++] = '*';
			break;
		}
		else str1[sn1++] = '?';
	}
}

void init() {
	memset(n, 0, sizeof(n));
	memset(f, 0, sizeof(f));
	while (gets(str) != NULL && str[0] != '\0') {
		tra();
	}
}

void solve() {
	make();
	for (int i = 0; i < n[1]; i++) {
		if (OK(i)) {
			printf("IMPOSSIBLE\n");
			if (t) printf("\n");
			return;
		}
	}
	printf("DEL %s.%s\n", str, str1);
	if (t) printf("\n");
}

int main() {
	scanf("%d%*c%*c", &t);
	while (t--) {
		init();
		solve();
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值