题意:
题意啊555,好难懂啊
大概意思是这个亚子的,就是给了一些文件夹,文件夹里面有子文件夹和文件,有n个是可以忽略的,m个不可以忽略的,问最少可以忽略多少个文件??(什么意思呢?也就是一个文件夹里面的文件都是可以忽略的,就只保留文件夹就好了)
思路:
可以忽略掉的文件假设有这两个:
a/b/a
c/b/c
(1)如果按单词存储,第二个文件会被删掉,然而第二个文件不可以删
(2)如果是按照前缀存的话呢??
-
我们先存的是不能删的文件路径的所有前缀
-
如果能删的路径和不能删的路径有公用前缀,就继续往下面找子文件夹,并且把没有出现过的目录标记一下,如果这个第二次被标记的目录再次出现,那么ans - 1(因为不能忽略一整个文件夹)
如果每个文件夹都可以直接忽略的话,ans = n就是答案,就没有任何意义了。
代码实现:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 3e6 + 5;
string a[maxn];
string b[maxn];
map<string,int>mp;
int main(){
int t;
scanf("%d",&t);
while(t--){
int n,m;
scanf("%d%d",&n,&m);
mp.clear();
for(int i = 1;i <= n;i++){
cin >> a[i];
}
string tmp = "";
for(int j = 1;j <= m;j++){
//为什么不能存单词???
/*
可以忽略掉的文件假设有这两个:
a/b/a
c/b/c
如果按单词存储,第二个文件会被删掉,然而第二个文件不可以删
如果是按照前缀存的话呢??
首先,我们先存的是不能删的文件路径的所有前缀
然后,如果能删的路径和不能删的路径有公用前缀,
就继续往下面找子文件夹,并且把没有出现过的目录标记一下,
如果这个第二次被标记的目录再次出现,那么ans - 1
(因为不能忽略一整个文件夹)
//如果每个文件都可以忽略的话,ans = n就是答案,就没有任何意义了。
*/
cin >> b[j];
int len = b[j].length();
tmp = "";
for(int k = 0;k < len;k++){
tmp += b[j][k];
if(b[j][k] == '/'){
mp[tmp] = 1;
}
}
}
tmp = "";
int ans = n;
//查询时的跳转问题??
for(int i = 1;i <= n;i++){
int len = a[i].length();
tmp = "";
for(int k = 0;k < len;k++){
tmp += a[i][k];
if(a[i][k] == '/'){
if(mp[tmp] == 1) continue;//公用前缀,接着查找
else if(mp[tmp] == 2){//再次出现,删掉
ans--;
break;
//而且已经合并了,肯定是不能再往下面找了啊!
}
else mp[tmp] = 2;//标记一下刚出现的文件目录
}
}
}
printf("%d\n",ans);
}
return 0;
}