列表

详情


NC50348. 背单词

描述

Lweb面对如山的英语单词,陷入了深深的沉思,「我怎么样才能快点学完,然后去玩三国杀呢?」。这时候睿智的凤老师从远处飘来,他送给了Lweb一本计划册和一大缸泡椒,然后凤老师告诉Lweb,我知道你要学习的单词总共有n个,现在我们从上往下完成计划表,对于一个序号为x的单词(序号都已经被填入):
  1. 如果存在一个单词是它的后缀,并且当前没有被填入表内,那他需要吃颗泡椒才能学会;
  2. 当它的所有后缀都被填入表内的情况下,如果在的位置上的单词都不是它的后缀,那么他吃x颗泡椒就能记住它;
  3. 当它的所有后缀都被填入表内的情况下,如果的位置上存在是它后缀的单词,所有是它后缀的单词中,序号最大为y,那么他只要吃x-y颗泡椒就能把它记住。
Lweb是一个吃到辣辣的东西会暴走的奇怪小朋友,所以请你帮助Lweb,寻找一种最优的填写单词方案,使得他记住这n个单词的情况下,吃最少的泡椒。

输入描述

输入一个整数n,表示Lweb要学习的单词数。接下来n行,每行有一个单词(由小写字母构成,且保证任意单词两两互不相同)。

输出描述

Lweb吃的最少泡椒数。

示例1

输入:

2
a
ba

输出:

2

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 173ms, 内存消耗: 52528K, 提交时间: 2019-12-10 00:44:41

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 510000;

struct Node {
  int cnt;
  int val;
  vector<int> ch;
  vector<pair<int, int>> chs;
};
Node nodes[MAXN];
int sz;
int cost;

void insert(string s) {
  int cur = 0;
  for (auto ch: s) {
    int id = ch - 'a';
    if (nodes[cur].ch.size() == 0) nodes[cur].ch.resize(26);
    int &nxt = nodes[cur].ch[id];
    if (nxt == 0) nxt = ++sz;
    nodes[nxt].cnt++;
    cur = nxt;
  }
  nodes[cur].val++;
}
void dfs1(int cur, int p) {
  if (nodes[cur].val) {
    nodes[p].chs.push_back({nodes[cur].cnt, cur});
    p = cur;
  }
  if (nodes[cur].ch.size() == 0) return;
  for (int i = 0; i < 26; i++) {
    int nxt = nodes[cur].ch[i];
    if (nxt == 0) continue;
    dfs1(nxt, p);
  }
}
int id;
long long dfs2(int cur, int fa) {
  int cid = id++;
  long long tot = cid - fa;
  sort(nodes[cur].chs.begin(), nodes[cur].chs.end());
  for (auto it: nodes[cur].chs) tot += dfs2(it.second, cid);
  return tot;
}

int main(){
  int n; cin >> n;
  while (n--) {
    string s; cin >> s;
    reverse(s.begin(), s.end());
    insert(s);
  }
  dfs1(0, 0);
  cout << dfs2(0, 0) << endl;
  return 0;
}

C++ 解法, 执行用时: 69ms, 内存消耗: 35320K, 提交时间: 2021-12-12 08:45:38

#include<bits/stdc++.h>
using namespace std;
struct node{
	string str;
	int len,s;
	vector <int> a;
}a[100001];
int trie[510001][26],f[510001],id[100001],tot;
long long ans;
bool cmp1(const node &x,const node &y){
	return x.len < y.len;
}
bool cmp2(const int &x,const int &y){
	return a[x].s < a[y].s;
}
void func(int i){
	id[i] = tot++;
	for (int j = 0;j < a[i].a.size();j++){
		ans += tot - id[i];
		func(a[i].a[j]);
	}
}
int main(){
	int n,t,temp,*p,i,j;
	cin>>n;
	for (i = 1;i <= n;i++){
		cin>>a[i].str;
		a[i].len = a[i].str.length();
		a[i].s = 0;
	}
	sort(a + 1,a + 1 + n,cmp1);
	for (i = 1;i <= n;i++){
		t = 0;
		temp = 0;
		for (j = a[i].len;j--;){
			p = &trie[t][a[i].str[j] - 'a'];
			if (!*p)*p = ++tot;
			t = *p;
			if (f[t]){
				temp = f[t];
				a[temp].s++;
			}
		}
		f[t] = i;
		a[temp].a.push_back(i);
	}
	for (i = 0;i <= n;i++)
		sort(a[i].a.begin(),a[i].a.end(),cmp2);
	tot = 0;
	func(0);
	cout<<ans;
	return 0;
}

上一题