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: 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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值