BZOJ1174 - Toponyms(trie)
题意
给你一个字符集合,你从其中找出一些字符串出来. 希望你找出来的这些字符串的最长公共前缀*字符串的总个数最大化.
思路
先建好trie树,然后dfs预处理每个子树下单词个数,同时计算最大值即可。
但是因为数据很大,字符可能的种类很多,要用tr树要用邻接表实现。实测vector也不行。
#include <bits/stdc++.h>
#define endl '\n'
#define IOS std::ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define FILE freopen(".//data_generator//in.txt","r",stdin),freopen("res.txt","w",stdout)
#define FI freopen(".//data_generator//in.txt","r",stdin)
#define FO freopen("res.txt","w",stdout)
#define pb push_back
#define mp make_pair
#define seteps(N) fixed << setprecision(N)
typedef long long ll;
using namespace std;
/*-----------------------------------------------------------------*/
ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
#define INF 0x3f3f3f3f
const int N = 5e6 + 10;
const double eps = 1e-5;
struct node {
char p;
int nt, ne;
};
int head[N];
node tr[N];
bool flag[N];
string s;
int si;
int ct;
ll ans;
void insert(const char str[]) {
int cur = 0;
for(int i = 0; str[i]; i++) {
bool found = false;
char p = str[i];
for(int e = head[cur]; e; e = tr[e].ne) {
if(tr[e].p == p) {
cur = tr[e].nt;
found = true;
break;
}
}
if(!found) {
tr[++si] = node {p, ++ct, head[cur]};
head[cur] = si;
cur = ct;
}
}
flag[cur] = 1;
}
int dfs(int cur, int dep) {
int cnt = flag[cur];
for(int e = head[cur]; e; e = tr[e].ne) {
cnt += dfs(tr[e].nt, dep + 1);
}
ans = max(ans, 1ll * dep * cnt);
return cnt;
}
int main() {
//FI;
IOS;
int n;
cin >> n;
cin.ignore();
for(int i = 1; i <= n; i++) {
getline(cin, s);
insert(s.c_str());
}
dfs(0, 0);
cout << ans << endl;
}