生活随笔
收集整理的這篇文章主要介紹了
C. Code a Trie(Trie+dfs+贪心)
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
C. Code a Trie
大佬題解,代碼基本就是抄的
對于每一個值計算所有串的LCA,也就是最長公共前綴,將該節(jié)點(Trie樹的節(jié)點)標記,對于這些字符串在LCA下面的點一定不存在(如果存在他們不會返回相同的值)
每個Trie樹中的節(jié)點只能被標記一次,并且從跟到LCA路徑上的變必須存在
dfs貪心計算每個子樹中最少的節(jié)點
插入時統(tǒng)計cnt[u]表示它的子樹中被標記為LCA的點的數(shù)量
- 如果cnt[u]>1,這個點必選,如果說該節(jié)點沒被標記為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
)
{sort(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;}int p
=0;for(int i
=0;i
<len
;i
++){cnt
[p
]++;int 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+贪心)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。