洛谷的文件夹(树形结构+DFS+字符串哈希)

洛谷的文件夹

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
*/

这里写图片描述

猜你喜欢

转载自blog.csdn.net/Stockholm_Sun/article/details/78332519