欢迎访问 生活随笔!

生活随笔

当前位置: 首页 >

C. Code a Trie(Trie+dfs+贪心)

发布时间:2023/12/3 46 豆豆
生活随笔 收集整理的这篇文章主要介绍了 C. Code a Trie(Trie+dfs+贪心) 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

C. Code a Trie

大佬题解,代码基本就是抄的

对于每一个值计算所有串的LCA,也就是最长公共前缀,将该节点(Trie树的节点)标记,对于这些字符串在LCA下面的点一定不存在(如果存在他们不会返回相同的值)

每个Trie树中的节点只能被标记一次,并且从跟到LCA路径上的变必须存在

dfs贪心计算每个子树中最少的节点
插入时统计cnt[u]表示它的子树中被标记为LCA的点的数量

  • 如果cnt[u]>1,这个点必选,如果说该节点没被标记为LCA,那么它可以替代它一个儿子称为那个值的LCA,如果被标记为LCA,它的儿子被标记那就必须选。
  • 如果cnt[u]=1,贪心选择该点,儿子不选
  • 如果cnt[u]=0,贪心不选
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0) #pragma GCC optimize(2) #include<set> #include<map> #include<cmath> #include<stack> #include<queue> #include<bitset> #include<random> #include<bitset> #include<string> #include<vector> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<unordered_map> #include<unordered_set> using namespace std; typedef long long ll; typedef pair<ll,int> pli; typedef pair<int,int> pii; const int N=500010; int n,a[N],b[N],cnt[N],ans; string s[N]; vector<string> g[N]; int tree[N][30],idx; bool lca[N]; void init() {cin>>n;int m=0;for(int i=1;i<=n;i++){cin>>s[i]>>a[i];m+=s[i].size();g[i].clear();}idx=0;for(int i=0;i<=m;i++)memset(tree[i],0,sizeof tree[i]);for(int i=0;i<=m;i++) lca[i]=0,cnt[i]=0; } bool cmp(string x,string y) {return x.size()<y.size(); } bool check(vector<string> &v) {//暴力寻找LCAsort(v.begin(),v.end(),cmp);int len=0;for(int i=0;i<v[0].size();i++){bool ok=1;for(int j=0;j<v.size()&&ok;j++)if(v[j][i]!=v[0][i]) ok=0;if(ok) len++;else break;}// Trie树插入int p=0;for(int i=0;i<len;i++){cnt[p]++;//子树中的lcaint c=v[0][i]-'a';if(tree[p][c]==-1) return 0; //节点不存在if(!tree[p][c]) tree[p][c]=++idx;p=tree[p][c];}if(lca[p]) return 0;lca[p]=1;cnt[p]++;// 标记一定不存在的点for(int i=0;i<v.size();i++){if(v[i].size()<=len) continue; int c=v[i][len]-'a';if(tree[p][c]>0) return 0;// 不存在的点存在了tree[p][c]=-1;}return 1; } void dfs(int u) {if(cnt[u]>1) ans++;bool fl=lca[u]==0;for(int i=0;i<26;i++){int son=tree[u][i];if(!son||son==-1) continue;if(cnt[son]==1){if(!fl) ans++;else fl=0;}else dfs(son);} } void work(int ca) {int m=0;for(int i=1;i<=n;i++)b[++m]=a[i];// 离散化sort(b+1,b+1+m);m=unique(b+1,b+1+m)-b-1;for(int i=1;i<=n;i++) a[i]=lower_bound(b+1,b+1+m,a[i])-b;// 统计相同值的字符串for(int i=1;i<=n;i++)g[a[i]].push_back(s[i]);// 判断进行插入for(int i=1;i<=m;i++)if(!check(g[i])){printf("Case #%d: -1\n",ca);return;}ans=0;cnt[0]++;dfs(0);printf("Case #%d: %d\n",ca,ans); } int main() {IO;int T=1;cin>>T;for(int ca=1;ca<=T;ca++){init();work(ca);}return 0; }

总结

以上是生活随笔为你收集整理的C. Code a Trie(Trie+dfs+贪心)的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。