洛谷的文件夹
Luogu P1738
题目描述
kkksc03是个非凡的空想家!在短时间内他设想了大量网页,然后总是交给可怜的lzn去实现。
洛谷的网页端,有很多文件夹,文件夹还套着文件夹。
例如:/luogu/application/controller表示根目录下有一个名称为luogu的文件夹,这个文件夹下有一个名称application的文件夹,其中还有名为controller的文件夹。
每个路径的第1个字符总是’/’,且没有两个连续的’/’,最后的字符不是’/’。所有名称仅包含数字和小写字母。
目前根目录是空的。kkksc03想好了很多应该有的文件夹路径名。问题是,需要是使这些文件夹都存在,需要新建几个文件夹呢?
输入输出格式
输入格式:
输入文件第1行为一个正整数N。
接下来N行,每行为一个描述路径的字符串,长度均不超过100。
输出格式:
输出应包含N行,每行1个正整数,第i行输出若要使第1个路径到第i个路径存在,最少需要新建多少个文件夹。
样例输入1:
2
/luogu/application/controller
/luogu/application/view
样例输入2:
3
/chicken
/chicken/egg
/chicken
样例输入3:
4
/a
/a/b
/a/c
/b/b
样例输出1:
3
4
样例输出2:
1
2
2
样例输出3:
1
2
3
5
说明
数据规模:
对于所有数据,N<=1000。
对于20%数据,有N<=20;
对于50%数据,有N<=200;
对于30%数据,有对于所有路径最多存在两个’/’(包含第1个字符)。
思路
首先,我们应该注意到这是一个树形结构,这个我们可以结合Trie树来理解,我们在处理每一个路径的时候,要把每一个“/”分隔开的子字符串处理成哈希数。
然后对于之前不存在的节点,就加一个节点来处理。如果存在,那我们就顺着它向下DFS,统计总更新的节点数。
需要注意的一点就是,要开一个超级根节点来连接第一等级。
代码
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<set>
using namespace std;
long long i,j,m,n,temp,tot,len,modd=23333333333;
string s;
long long hd[100001],cnt,cc;
long long par[101];
struct data
{
long long y,nxt,chr;
}a[100001];
long long r()
{
long long ans=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9')
{
if(ch=='-')
f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
ans*=10;
ans+=ch-'0';
ch=getchar();
}
return ans*f;
}
void dfs(long long x,long long t)
{
long long kk=0;
if(t==cnt+1) return;
for(long long p=hd[x];p;p=a[p].nxt)
{
if(par[t]==a[p].chr)
{
dfs(a[p].y,t+1);
kk=1;
break;
}
}
if(!kk)
{
a[++temp].chr=par[t];
a[temp].nxt=hd[x];
a[temp].y=++tot;
hd[x]=temp;
dfs(tot,t+1);
}
}
int main()
{
n=r();
++temp;
tot++;
for(i=1;i<=n;i++)
{
cin>>s;
len=s.size();
cnt=0,cc=0;
for(j=1;j<len;j++)
{
if(s[j]=='/')
par[++cnt]=cc,cc=0;
else
cc*=13131,cc%=modd,cc+=s[j];
}
par[++cnt]=cc;
dfs(1,1);
cout<<tot-1<<endl;
}
return 0;
}
/*
2
/luogu/application/controller
/luogu/application/view
*/