• P3294 [SCOI2016]背单词


    首先第一个是非常不划算的 所以我们想办法先将没有前缀的前放进去

    第二就是第三的特殊情况

    有公共后缀的一定是连在一起的 几堆不同公共后缀的 一定是先排数量小的一堆 因为这样对后面几堆产生的贡献最小

    最后说白了就是先按照sz排序 最后按照dfs序走一遍dfs统计答案就好

    #include<cstdio>
    #include<string>
    #include<algorithm>
    #include<iostream>
    #include<vector>
    using namespace std;
    string a[100005];
    int trie[510005][26],dp[510005],num[510005],numm;
    bool yes[510005];
    vector<int> edge[510005];
    long long ans;
    bool cmp(int x,int y){
        return dp[x]<dp[y];
    }
    void dfs(int x){
        int i;
        for(i=0;i<edge[x].size();i++){
            dfs(edge[x][i]);
            dp[x]+=dp[edge[x][i]];
        }
        sort(edge[x].begin(),edge[x].end(),cmp);
    }
    void dfs1(int x){
        int i;
        num[x]=numm++;
        for(i=0;i<edge[x].size();i++){
            ans+=numm-num[x];
            dfs1(edge[x][i]);
        }
    }
    bool cmp1(string x,string y){
        return x.size()<y.size();
    }
    int main(){
    	int n,i,j,cnt=0;
    	scanf("%d",&n);
    	for(i=1;i<=n;i++){
    		cin>>a[i];
    	}
        sort(a+1,a+n+1,cmp1);
    	for(i=1;i<=n;i++){
    		int len,u=0,bj=0;
    		for(j=a[i].size()-1;j>=0;j--){
    			if(!trie[u][a[i][j]-'a']){
    				trie[u][a[i][j]-'a']=++cnt;
    			}
                if(yes[u]){
                    bj=u;
                }
    			u=trie[u][a[i][j]-'a'];
    		}
            edge[bj].push_back(u);
            dp[u]=yes[u]=1;
    	}
        dfs(0);
        dfs1(0);
    	printf("%lld\n",ans);
    	return 0;
    }
  • 相关阅读:
    JavaScript DOM 编程艺术 公用方法
    JavaScript DOM 编程艺术
    Echart 的formatter及重写line chart
    PHP 导出csv
    Linux 搭建PHP环境
    学习新思路
    fork产生子进程利用pipe管道通信
    进程间通信 管道
    进程间通信(IPC) 简介
    java 多态
  • 原文地址:https://www.cnblogs.com/wzxbeliever/p/16093426.html
Copyright © 2020-2023  润新知