P3294 [SCOI2016]背單詞
阿新 • • 發佈:2022-04-02
首先第一個是非常不划算的 所以我們想辦法先將沒有字首的前放進去
第二就是第三的特殊情況
有公共字尾的一定是連在一起的 幾堆不同公共字尾的 一定是先排數量小的一堆 因為這樣對後面幾堆產生的貢獻最小
最後說白了就是先按照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; }