欢迎访问我的CCF认证解题目录
题目描述
思路过程
整理一下题目规则
- 绝对路径:以“/”开头
- 相对路径:以“..”或“.”开头
- 空字符串表示当前目录
- 对于“.”,如果在开头,则替换为当前目录,如果不在开头,则没意义
- 对于“..”,如果在开头,则替换为当前目录的上一级目录,如果不在开头,则表示目前所在目录的上一级目录
- 根目录的上一级目录为根目录
- 连续的“///”相当于“/”
- 输出时要去掉结尾的“/”,如果只有“/”,则不用去除
这个题目我第一次写没有满分,只得了70分。思路如下:
用father变量表示当前目录,用ffather表示当前目录的上一目录,而后读入所有的路径,对于每个路径,判断是否为空字符串,如果是,则str=father,如果是以“..”开头,则str = ffather+str(去除了前面两个..),如果是以“.”开头,则str = 当前目录+str。最后去除“.”和重复的“/”。
输出的话,对于每个路径(经过上面的步骤,现在只需考虑“..”),查找“..”的下标,如果找到,用temp记录“..”后面的内容,接着判断是否为两层结构,如果是的话,str就去掉一层“/”后加上temp,如果不是,则str直接为“/”+temp。最后输出时检测是否为“/”结尾。
没错,我直接在原有字符串上硬刚w(゚Д゚)w,跟后面的满分思路差远了
错误的地方:判断开头部分,我只是判断开头是否为“..”和“.”,如果开头是“...”呢?而且我判断的时候也没有加上等于号,如果刚好是两位(..)和一位(.)我也没进行判断(╯‵□′)╯︵┻━┻
总结:对于匹配,我只处理了前面部分,后面如果有相同的前缀我也一样处理
70分代码
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner in = new Scanner(System.in);
int n = in.nextInt();
in.nextLine();
String father = in.nextLine();
String ffather = "/";
if ( father.matches("/[^/]+/.+") ) {//当前目录有两层
ffather = father.substring(0, father.lastIndexOf('/') );
}
String[] str = new String[n];
for ( int i = 0; i < str.length; i++ ) {
str[i] = in.nextLine();
//空字符串
if ( str[i].equals("") ) str[i] = father;
//这里开始错了,是>=,不是>,而且我只判断了前两位,如果名字为“...”就错了
//而且如果是“...”的话,输出也是错的
//以“..”开头
if ( str[i].length() > 2 && str[i].substring(0, 2).equals("..") ) {
if ( str[i].length() > 3 ) str[i] = ffather + str[i].substring(2);
else str[i] = ffather;
}
//如果开头是.,则替换
else if ( str[i].length() > 1 && str[i].charAt(0) == '.' ) {
if ( str[i].length() > 2 ) str[i] = father+str[i].substring(1);
else str[i] = father;
}
str[i] = str[i].replaceAll("/\\.(?!\\.)", "");//删除“/.”
str[i] = str[i].replaceAll("/+", "/");//删除重复“//”
}
//没有连续的“//”,没有以“.”和“..”开头,没有空字符串,都是以“/”开头
//没有“.”,只需处理“..”
for ( int i = 0; i < str.length; i++ ) {
for ( int index = str[i].indexOf(".."); index != -1; index = str[i].indexOf("..")) {
String temp = "";//“..”后面的内容
//获取“..”后面的内容
if ( str[i].length() > index + 2 ) temp = str[i].substring(index+2);
//去除“..”的前一目录
// System.out.println(str[i].substring(0, str[i].lastIndexOf("/", index)));
if ( str[i].substring(0, str[i].lastIndexOf("/", index)).matches("/[^/]+/.+") ) {
str[i] = str[i].substring(0, str[i].lastIndexOf("/", index-2))+temp;
} else str[i] = "/"+temp;
//去除连续的“//”
str[i] = str[i].replaceAll("/+", "/");
}
//输出去掉结尾的“/”
if ( str[i].length() > 1 && str[i].charAt(str[i].length()-1) == '/' ) {
System.out.println(str[i].substring(0, str[i].length()-1));
} else System.out.println(str[i]);
}
}
}
100分思路
参考了网上大佬的思路,用path表示当前路径,用str读入路径,如果为空,str=path,如果不是“/”开头,说明不是绝对路径,str=path+'/'+str,去除连续的"/"。此时只需正规化就好了。
用split分割字符串,定义一个向量数组,分割完后,遍历数组。
如果是"."就跳过,如果是".."且向量数组的大小大于0,就删除最后一个(上一目录),如果不是"..",就加入向量数组
接着按格式输出就ok了,网上大佬就是大佬,思路好简洁,想起我的硬刚,留下了学渣的眼泪/(ㄒoㄒ)/~~。
100分代码
import java.util.ArrayList;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
in.nextLine();
String path = in.nextLine();//当前路径
for ( int i = 0; i < n; i++ ) {
String str = in.nextLine();
if ( str.equals("") ) str = path;//空字符串
if ( str.charAt(0) != '/' ) str = path + '/' + str;//不是绝对路径
str = str.replaceAll("/+", "/");//去除连续的“/”
String[] temp = str.split("/");
ArrayList<String> ans = new ArrayList<String>();
for ( int j = 1; j < temp.length; j++ ) {
//j=1开始,第一个是“”,跳过,若当前目录为“/”的话,分割完后length==0,不影响
if ( temp[j].equals(".") ) continue;//读者可以思考一下这个为什么不可以省略
else if ( temp[j].equals("..") && ans.size() > 0 ) ans.remove(ans.size()-1);
else if ( !temp[j].equals("..") ) ans.add(temp[j]);
}
System.out.print("/");//读者可以思考一下为什么不直接放for循环里
for ( int j = 0; j < ans.size(); j++ ) {
if ( j != 0 ) System.out.print("/");
System.out.print(ans.get(j));
}
System.out.println();
}
}
}