uva 502 DEL command

题目地址:

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=443

题目描述:



  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*.*
题意:

构造一个严格过滤串,将含有+号的串过滤掉,而含有-号的串留在这里,表示要删除的文件清单。

题解:

字符串处理。

这题的思路我并没有用到DFS,因为对数据的模拟发现,如果在输入要删除的文件当中,构造一个最严格的过滤串,只要在输入不要删除的文件中过滤串都能过滤掉这些不删除的文件则表示有解,而只要有一个不需要删除的文件没有被过滤串过滤掉 则表示整个情况是impossible的。

这样我们可以把输入要删除文件分一堆,不删除文件分一堆。先遍历要删除文件,从而构造一个最严格过滤串(这样就不用回溯多次构造过滤串),然后用获得的过滤串去遍历不删除的文件,只要全部过滤掉,这输出这个过滤串,反之 只要有一个 没有被过滤掉直接退出遍历,输出impossible。

关于过滤串的构造:1、对应位字符相等,则过滤串对应位为该字符。2、对应位字符串不等,则过滤串该位为 '?'。3、对应串不等,但是出现在末端,比如其中一个串到达了'.'位置或者是‘\0’位置,则过滤串对应位为‘*’。

注意:字符串模拟要小心,特别是指针的移动细节,比较字符,跳转等等。总之就是要模拟就必须要非常细心。

剪枝:当不删除文件数量为0时,则表示输入的文件全部删除,没必要去生成最严格过滤串,直接输出 DEL *.* 即可。

两次WA的原因:

第一次:在处理过滤串过滤不删除文件的遍历过程中,到达'.'后 退出循环,没有考虑可能是这样的情况 过滤串指针指向'*'位置 而它的后一位就是'.'位置了 而不删除文件指针指向了'.'导致循环提早跳出,然后直接判断不等得出相关结论。实际上 '*'与'.'是符合相容情况的如何 A*. 与A.  是可以相容的 并不排斥。

第二次:过滤串是要检查所有的不删除文件们后  这些都能过滤才能得出结论 说明 过滤串是有效的,而自己仅在判断一个不删除文件的过程中,直接用return 提前结束了不删除文件的遍历。这样并不能保证所有的不删除文件都能过滤。

代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <iostream>
#include <algorithm>
using namespace std;
char substr[1000+5][15+5]={'\0'};
int subcnt=0;
char addstr[1000+5][15+5]={'\0'};
int addcnt=0;
int M=0;
char delstr[15+5]={'\0'};//delete string
char instr[15+5]={'\0'};//input string
/*struct the delstr*/
int FindDelStr()
{
	char prestr[15]={'\0'};//compare string
	char rearstr[15]={'\0'};
	int i1=0,i2=0,j=0,k=0;
	if(subcnt>=1)
	{
		strcpy(prestr,substr[0]);
		strcpy(delstr,prestr);
	}
	for(k=1;k<=subcnt-1;k++)
	{
		strcpy(rearstr,substr[k]);
		//get the delstr pattern
		i1=0;
		i2=0;
		j=0;
		while(prestr[i1]!='.'&&rearstr[i2]!='.')//~~~~~.  left of the '.'
		{
			if(prestr[i1]==rearstr[i2])
			{
				delstr[j]=prestr[i1];
			}
			else
			{
				if(prestr[i1]=='*')
				{
					//let the i2 point the left 1 bit of the '.'
					while(rearstr[i2]!='.')
					{
						i2++;
					}
					i2--;//point the left 1 bit of the '.'
					delstr[j]='*';
				}
				else
				{
					delstr[j]='?';
				}
			}
			i1++;
			i2++;
			j++;
		}
		if(prestr[i1]==rearstr[i2])//=='.' besides  i1==i2
		{
			delstr[j]='.';
			j++;
		}
		else
		{
			delstr[j]='*';
			j++;
			delstr[j]='.';
			j++;
		}
		while(prestr[i1]!='.')
		{
			i1++;
		}
		i1++;//i1 point the . right
		while(rearstr[i2]!='.')
		{
			i2++;
		}
		i2++;//i2 point the . right

		while(prestr[i1]!='\0'&&rearstr[i2]!='\0')//~~~~~.  left of the '.'
		{
			if(prestr[i1]==rearstr[i2])
			{
				delstr[j]=prestr[i1];
			}
			else
			{
				if(prestr[i1]=='*')
				{
					//let the i2 point the left 1 bit of the '\0'
					while(rearstr[i2]!='\0')
					{
						i2++;
					}
					i2--;//point the left 1 bit of the '\0'
					delstr[j]='*';
				}
				else
				{
					delstr[j]='?';
				}
			}
			i1++;
			i2++;
			j++;
		}
		if(prestr[i1]==rearstr[i2])//=='.' besides  i1==i2
		{
			delstr[j]='\0';
			j++;
		}
		else
		{
			delstr[j]='*';
			j++;
			delstr[j]='\0';
			j++;
		}
		strcpy(prestr,delstr);//next update the delstr
	}
	return(0);
}
/*test the delstr whether can test the no del string*/
bool TestNoDelStr()
{
	if(addcnt==0)
	{
		strcpy(delstr,"*.*");
		return(true);
	}
	int i=0,j=0,k=0;
	int flag=0;//flag=1 indicate it is match for the delstr
	for(k=0;k<=addcnt-1;k++)
	{
		i=0;
		j=0;
		flag=1;
		while(delstr[i]!='.'&&addstr[k][j]!='.')
		{
			if(delstr[i]!=addstr[k][j])
			{
				if(delstr[i]=='?')
				{

				}
				else if(delstr[i]=='*')
				{
					while(addstr[k][j]!='.')//let the point the '.' left one bit
					{
						j++;
					}
					j--;
				}
				else
				{
					flag=0;
					//return(true);
				}
			}
			i++;
			j++;
		}
		if(delstr[i]=='*')
		{
			while(addstr[k][j]!='.')//let the point the '.' left one bit
			{
				j++;
			}
			j--;
			i++;
			j++;
		}
		if(delstr[i]!=addstr[k][j])//must reach '.' at the same times
		{
			flag=0;
			//return(true);
		}
		i++;
		j++;//point the . right
		while(delstr[i]!='\0'&&addstr[k][j]!='\0')
		{
			if(delstr[i]!=addstr[k][j])
			{
				if(delstr[i]=='?')
				{

				}
				else if(delstr[i]=='*')
				{
					while(addstr[k][j]!='\0')//let the point the '.' left one bit
					{
						j++;
					}
					j--;
				}
				else
				{
					flag=0;
					//return(true);
				}
			}
			i++;
			j++;
		}
		if(delstr[i]=='*')
		{
			while(addstr[k][j]!='\0')//let the point the '.' left one bit
			{
				j++;
			}
			j--;
			i++;
			j++;
		}
		if(delstr[i]!=addstr[k][j])//must reach '\0' at the same times
		{
			flag=0;
			//return(true);
		}
		if(flag)
		{
			return(false);
		}
	}
	return(true);//the delstr match the all addstr then return false that this delstr is invalid
}
/*for test*/
int test()
{
	return(0);
}
/*main process*/
int MainProc()
{
	scanf("%d",&M);
	getchar();//eat the \n
	getchar();
	while(M--)
	{
		//init
		subcnt=0;
		addcnt=0;
		memset(delstr,'\0',sizeof(delstr));
		while(fgets(instr,15,stdin)!=NULL&&instr[0]!='\n')//not the EOF,EOF is int type
		{
			int inlen=strlen(instr);
			instr[inlen-1]='\0';//cover the \n
			inlen--;
			if(strchr(instr,'.')==NULL)
			{
				instr[inlen]='.';
				instr[inlen+1]='\0';
				inlen++;
			}
			if(instr[0]=='-')//- delete string
			{
				strcpy(substr[subcnt],instr+1);//abandon the + or -
				subcnt++;
			}
			else//+ do not delete string
			{
				strcpy(addstr[addcnt],instr+1);
				addcnt++;
			}
		}
		//test
		int i=0;
		if(addcnt>0)
		FindDelStr();//if addcnt==0  we can del *.*
		if(TestNoDelStr())//the delstr is valid
		{
			printf("DEL %s\n",delstr );
		}
		else//impossible
		{
			printf("IMPOSSIBLE\n");
		}
		//blank line between datasets
		if(M>0)
		{
			printf("\n");
		}
	}
	return(0);
}
int main(int argc, char const *argv[])
{
	/* code */
	MainProc();
	return 0;
}


你可能感兴趣的:(字符串,遍历,指针)