- 前缀和问题,考虑字典树
- 由于字典树的存储结构,从上到下贪心是不行的
- 但是可以从下往上:当前这个子树的大小小于等于k就不管它,等着上面一块处理,大于k就依次减去最大的子树,剩余的sz等着上面一块处理。
#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false) ,cin.tie(0), cout.tie(0);
//#pragma GCC optimize(3,"Ofast","inline")
#define ll long long
//#define int long long
const int N = 3e5 + 5;
const int M = 1e5 + 5;
const int INF = 0x3f3f3f3f;
const ll LNF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
const double PI = acos(-1.0);
int n, k, tot = 1;
int trie[N][26];
int ed[N], sz[N]; int ans;
void add ( string ss ) {
int p = 1;
for ( auto i : ss ) {
int ch = i - 'a';
if( ! trie[p][ch] ) {
trie[p][ch] = ++ tot;
}
p = trie[p][ch];
}
++ ed[p];
}
void dfs ( int p ) {
sz[p] += ed[p];
vector<int> ve;
for ( int i = 0; i < 26; ++ i ) {
int ne = trie[p][i];
if( ne ) dfs( ne ), ve.push_back( sz[ne] ), sz[p] += sz[ne];
}
if( sz[p] <= k) return;
sort( ve.begin(), ve.end(), []( int A, int B ){ return A > B; } );
for ( auto i : ve) {
++ ans; sz[p] -= i;
if(sz[p] <= k) break;
}
}
int main () {
IOS;
cin >> n >> k;
for ( int i = 1; i <= n; ++ i ) {
string ss; cin >> ss;
add(ss);
}
dfs(1);
cout << ans + (sz[1] > 0) << '\n'; // + 剩余的一块处理
return 0;
}