• UVA11732 "strcmp()" Anyone?


    思路

    有点麻烦的Trie树题

    注意到每个节点的贡献是(深度(根的深度是0)乘2+1)乘上在这个点分叉的字符串个数,所以全部插入之后dfs一遍即可(为了避免两个字符串一样的情况,还应该特判一下最后的中止节点)

    代码

    字符集太大需要用邻接表存才能跑过

    直接存边的TLE代码

    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <set>
    #define int long long
    using namespace std;
    signed Trie[4000100][65];
    int Nodecnt,sz[4000100],ans=0,root,n;
    char s[4010][1010];
    int tonum(char c){
        if(c>='a'&&c<='z')
            return c-'a';
        else if(c=='a'+26)
            return 26;
        else if(c>='A'&&c<='Z')
            return c-'A'+27;
        else if(c>='0'&&c<='9')
            return c-'0'+54;
    }
    void insert(char *s,int len){
        int o=root;
        sz[o]++;
        for(int i=0;i<len;i++){
            if(!Trie[o][tonum(s[i])])
                Trie[o][tonum(s[i])]=++Nodecnt;
            o=Trie[o][tonum(s[i])];
            sz[o]++;
        }
    }
    void dfs(int o,int dep,int isend=0){
        if(!isend){
            int midt=0;
            for(int i=0;i<65;i++){
                if(Trie[o][i]){
                    sz[o]-=sz[Trie[o][i]];
                    midt+=sz[Trie[o][i]]*sz[o];
                }
            }
            ans+=(dep+1)*midt;
            for(int i=0;i<65;i++){
                if(Trie[o][i]){
                    dfs(Trie[o][i],dep+2,(i==26));
                }
            }
        }
        else{
            ans+=(sz[o]-1)*(sz[o])/2*dep;
        }
    }
    void init(void){
        for(int i=0;i<=Nodecnt;i++){
            for(int j=0;j<65;j++)
                Trie[i][j]=0;
            sz[i]=0;
        }
        ans=0;
        Nodecnt=1;
        root=1;
    }
    signed main(){
        // freopen("test.in","r",stdin);
        // freopen("test.out","w",stdout);
        Nodecnt=1;
        root=1;
        ans=0;
        int cnt=0;
        while(scanf("%lld",&n)==1&&n){
            ++cnt;
            for(int i=1;i<=n;i++){
                scanf("%s",s[i]+1);
                int len=strlen(s[i]+1);
                s[i][len+1]='a'+26;
                insert(s[i]+1,len+1);
            }
            dfs(root,0);
            printf("Case %lld: %lld
    ",cnt,ans);
            init();
        }
        return 0;
    }
    

    邻接表存边的AC代码

    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <set>
    #define int long long
    using namespace std;
    signed fir[4000100],nxt[4000100],v[4000100],num[4000100],Ecnt=0;
    int Nodecnt,sz[4000100],ans=0,root,n;
    char s[4010][1010];
    int tonum(char c){
        if(c>='a'&&c<='z')
            return c-'a';
        else if(c=='a'+26)
            return 26;
        else if(c>='A'&&c<='Z')
            return c-'A'+27;
        else if(c>='0'&&c<='9')
            return c-'0'+54;
    }
    void addedge(int ui,int vi){
        ++Ecnt;
        v[Ecnt]=vi;
        nxt[Ecnt]=fir[ui];
        fir[ui]=Ecnt;
    }
    void insert(char *s,int len){
        int o=root;
        sz[o]++;
        for(int i=0;i<len;i++){
            int vx;
            bool f=false;
            for(int j=fir[o];j;j=nxt[j])
                if(num[v[j]]==tonum(s[i])){
                    vx=v[j];
                    f=true;
                    break;
                }
            if(!f){
                vx=++Nodecnt;
                num[vx]=tonum(s[i]);
                addedge(o,vx);
            }
            o=vx;
            sz[o]++;
        }
    }
    void dfs(int o,int dep,int isend=0){
        if(!isend){
            int midt=0;
            for(int i=fir[o];i;i=nxt[i]){
                sz[o]-=sz[v[i]];
                midt+=sz[v[i]]*sz[o];
            }
            ans+=(dep+1)*midt;
            for(int i=fir[o];i;i=nxt[i]){
                dfs(v[i],dep+2,(num[v[i]]==26));
            }
        }
        else{
            ans+=(sz[o]-1)*(sz[o])/2*dep;
        }
    }
    void init(void){
        ans=0;
        Nodecnt=1;
        root=1;
        Ecnt=0;
        memset(sz,0,sizeof(sz));
        memset(fir,0,sizeof(fir));
        memset(nxt,0,sizeof(nxt));
        memset(v,0,sizeof(v));
        memset(num,0,sizeof(num));
    }
    signed main(){
        // freopen("test.in","r",stdin);
        // freopen("test.out","w",stdout);
        Nodecnt=1;
        root=1;
        ans=0;
        int cnt=0;
        while(scanf("%lld",&n)==1&&n){
            ++cnt;
            for(int i=1;i<=n;i++){
                scanf("%s",s[i]+1);
                int len=strlen(s[i]+1);
                s[i][len+1]='a'+26;
                insert(s[i]+1,len+1);
            }
            dfs(root,0);
            printf("Case %lld: %lld
    ",cnt,ans);
            init();
        }
        return 0;
    }
    
  • 相关阅读:
    数据库中Schema和Database有什么区别
    VS2015智能提示由英文改为中文
    分配数据库角色权限
    【转载】使用局部标准差实现图像的局部对比度增强算法
    RS485的常用电路设计
    c++对txt文件的读取与写入 【转载】
    OpencV使用fitEllipse拟合椭圆后,获取椭圆参数 【转载】
    C++指定编译代码语句(模块)
    C++自动创建文件夹
    vs2015中复制C++ DLL 和.pdb文件到C#工程中bin目录的设置方法
  • 原文地址:https://www.cnblogs.com/dreagonm/p/10690046.html
Copyright © 2020-2023  润新知