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: DELwildcard
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*.*
题目大意:问能不能构造出一个过滤串,实现删除所有要删除的文件,保留不删除的文件。
第一行是输入的样例数t,中间隔着一个空行。
然后每组给出一些文件名,两个样例以空行为分界。
文件名前缀是'-'就是要删除的,而如果是'+'就是要保留的。
?'代表任意字母, '*'代表任意多个字母,'*'只能在文件名或者后缀名的末尾出现。
过滤串的构造方法:
1、对应位字符相等,则过滤串对应位为该字符。
2、对应位字符串不等,则过滤串该位为 '?'。
3、对应串不等,但是出现在末端,比如其中一个串到达了'.'位置或者是‘\0’位置,则过滤串对应位为‘*’。
例如题目所给出的样例,其实题目所给出的标准输出,并不是规范的答案
-BP.EXE
-BPC.EXE
+TURBO.EXE
我们把要删的放在一起
-BP.EXE
-BPC.EXE
它们相同的部分是,这才是标准答案。
BP*.EXE(*代表后面的东西无所谓)
所以我们就是把要删的摆在一起,一位一位判断,如果某一位上字符全部都一样,就在结果字符串的这一位填上这个字符,
如果不一样,就填上'?'代替,如果某一个串已经判断到结束了,但是其他的还没完,就加上一个'*'然后结束,
然后用这个串去和所有要保留的串判断,如果删掉其中任意一个,那么就只能输出IMPOLLIBLE,全都不会删,就输出结果字符串。
思路:要把字符串分割为两部分,文件名部分,和后缀部分,分别对文件名进行以上操作,然后对后缀名做以上操作,
最后输出 文件名过滤串 + '.' + 后缀过滤串,然后用该过滤串判断保留文件会不会被删除。
附上一组测试样例
input
9
-A
-AA
-AAA
+AAAA
-AAA
-AAAA
+AA
-AB
-AA
+AAAA
-AB
-BB
+ABAA
-X.A
-X.AA
+X.AAA
-X.AB
-X.AA
+X.AAA
-X.AB
-X.BB
+X.ABA
-X.A
-X.AA
+X
-X.AA
-X.AAA
+X.A
-X.AB
-X.BB
+X.ABA
-X.A
output
IMPOSSIBLE
DEL AAA*.
DEL A?.
DEL ?B.
IMPOSSIBLE
DEL X.A?
DEL X.?B
IMPOSSIBLE
IMPOSSIBLE
AC代码
#include <stdio.h>
#include <string.h>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 1010;
const int INF = 0x3f3f3f3f;
struct Node {
string name; //文件名
string extend;//拓展名
}keep[N],del[N];
string ansn,anse;
int maxn,minn; //保存最长和最短的长度
int maxe,mine;
int numk,numd; //保留的字符串和删除的字符串的个数
bool judge() {
bool flag1,flag2;
//cout << "DEL " << ansn << "." << anse << endl;
//判断前面前缀
for(int i = 0; i < numk; i++) {
flag1 = true; //可以删除
for(int j = 0; j < minn && j < keep[i].name.size(); j++) {
if(ansn[j] == '?') {
continue;
}
if(keep[i].name[j] != ansn[j]) {
flag1 = false;//不可删除
break;
}
}
if(flag1) { //如果可以删除在判断长度是否合法
if(ansn[ansn.size()-1] == '*') {
if(ansn.size()-1 > keep[i].name.size()) {
flag1 = false;
}
}else if(ansn.size() != keep[i].name.size()) {
flag1 = false;
}
}
if(flag1) {
break;
}
}
//判断后缀名是否可以删除
for(int i = 0; i < numk; i++) {
flag2 = true; //可以删除
for(int j = 0; j < mine && j < keep[i].extend.size(); j++) {
if(anse[j] == '?') {
continue;
}
if(keep[i].extend[j] != anse[j]) {
flag2 = false;
break;
}
}
if(flag2) {
if(anse[anse.size()-1] == '*') {
if(anse.size()-1 > keep[i].extend.size()) {
flag2 = false;
}
}else if(anse.size() != keep[i].extend.size()) {
flag2 = false;
}
}
if(flag2) {
break;
}
}
if(flag1 && flag2) {
return false;
}else {
return true;
}
}
void solve() { //构造过滤串
for(int i = 0; i < minn; i++) {
bool flag = true;
for(int j = 1; j < numd; j++) {
if(del[j-1].name[i] != del[j].name[i]) {
flag = false;
break;
}
}
if(flag) {
ansn += del[0].name[i];
}else {
ansn += '?';
}
}
if(minn < maxn) {
ansn += '*';
}
for(int i = 0; i < mine; i++) {
bool flag = true;
for(int j = 1; j < numd; j++) {
if(del[j].extend[i] != del[j-1].extend[i]) {
flag = false;
break;
}
}
if(flag) {
anse += del[0].extend[i];
}else {
anse += '?';
}
}
if(mine < maxe) {
anse += '*';
}
if(judge()) {
cout << "DEL " << ansn << "." << anse << endl;
}else {
cout<<"IMPOSSIBLE"<<endl;
}
}
void init() {
ansn = "";
anse = "";
maxn = maxe = -INF;
minn = mine = INF;
numd = numk = 0;
}
void input() {
string str;
while(getline(cin,str)) { //分割并保存字符串
if(str[0] == '\0') {
break;
}
if(str[0] == '-') { //保存删除的文件名
del[numd].name = "";
del[numd].extend = "";
int flag = 0;
for(int i = 1; i < str.size(); i++) {
if(str[i] == '.') {
flag++;
continue;
}
if(!flag) {
del[numd].name += str[i];
}else {
del[numd].extend += str[i];
}
}
maxn = max(maxn,(int)del[numd].name.size());
minn = min(minn,(int)del[numd].name.size());
maxe = max(maxe,(int)del[numd].extend.size());
mine = min(mine,(int)del[numd].extend.size());
numd++;
}
else {
keep[numk].name = "";
keep[numk].extend = "";
int flag = 0;
for(int i = 1; i < str.size(); i++) {
if(str[i] == '.') {
flag++;
continue;
}
if(!flag) {
keep[numk].name += str[i];
}else {
keep[numk].extend += str[i];
}
}
numk++;
}
}
}
int main() {
int t;
while(cin >> t) {
cin.get();
cin.get();
while(t--) {
init();
input();
solve();
if(t) {
cout << endl;
}
}
}
return 0;
}