试题描述
|
Lweb 面对如山的英语单词,陷入了深深的沉思,「我怎么样才能快点学完,然后去玩三国杀呢?」。这时候睿智的凤老师从远处飘来,他送给了 Lweb 一本计划册和一大缸泡椒,然后凤老师告诉 Lweb ,我知道你要学习的单词总共有 n个,现在我们从上往下完成计划表,对于一个序号为 x 的单词(序号 1…x−1 都已经被填入):
如果存在一个单词是它的后缀,并且当前没有被填入表内,那他需要吃 n×n颗泡椒才能学会; 当它的所有后缀都被填入表内的情况下,如果在 1…x−1的位置上的单词都不是它的后缀,那么你吃 x 颗泡椒就能记住它; 当它的所有后缀都被填入表内的情况下,如果 1…x−1 的位置上存在是它后缀的单词,所有是它后缀的单词中,序号最大为 y ,那么你只要吃 x−y 颗泡椒就能把它记住。 Lweb 是一个吃到辣辣的东西会暴走的奇怪小朋友,所以请你帮助 Lweb,寻找一种最优的填写单词方案,使得他记住这 n 个单词的情况下,吃最少的泡椒。 |
输入
|
输入一个整数 n ,表示 Lweb 要学习的单词数。接下来 n 行,每行有一个单词(由小写字母构成,且保证任意单词两两互不相同,1≤n≤100000 ,所有字符的长度总和 1≤∣len∣≤510000 )
|
输出
|
Lweb 吃的最少泡椒数。
|
输入示例
|
2
a ba |
输出示例
|
2
|
其他说明
|
数据范围与提示
1≤n≤100000 ,所有字符的长度总和 1≤∣len∣≤510000 |
这道题考什么呢?
是读题啦!
写了两天的代码,发现结果错误,然后看题解,发现我理解错了
我这人平时是很温和的,也不轻易D人,然而这次有点忍不了
这TM是什么JB玩意儿,出题人教你语文的体育老师还健在吗
别的题解D的都比我好,大家有兴趣就可以去看
首先是trie树无疑了,但是我们发现只与后缀有关
所以要反向存
然后就是一波贪心
然后就是这题最好别做
还有就是要卡int
下面给出代码:
#include<iostream> #include<cmath> #include<cstdio> #include<cstdlib> #include<cstring> #include<string> #include<algorithm> using namespace std; inline long long rd(){ long long x=0,f=1; char ch=getchar(); for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-1; for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0'; return x*f; } inline void write(long long x){ if(x<0) putchar('-'),x=-x; if(x>9) write(x/10); putchar(x%10+'0'); return ; } long long n; long long trie[510006][50]; long long total=1; long long len; long long vis[510006]; long long head[510006],nxt[510006],to[510006]; long long tot=0; void add(long long x,long long y){ tot++; to[tot]=y; nxt[tot]=head[x]; head[x]=tot; return ; } char x[510006]; void pre(long long v){ long long c=1; for(long long i=len;i>=1;i--){ long long s=x[i]-'a'; if(!trie[c][s]) trie[c][s]=++total; c=trie[c][s]; } vis[c]=v; return ; } void dfs(long long x,long long y){ if(vis[x]) add(y,vis[x]),y=vis[x]; for(long long i=0;i<=30;i++) if(trie[x][i]) dfs(trie[x][i],y); return ; } struct node{ long long dis,v; }s[510006]; long long num[510006]; long long ans=0; bool cmp(node x,node y){ return x.dis<y.dis; } long long f[110006]; void dfss(long long x){ num[x]=1; for(long long e=head[x];e;e=nxt[e]){ dfss(to[e]); num[x]+=num[to[e]]; } long long cnt=0; for(long long e=head[x];e;e=nxt[e]){ s[++cnt].dis=num[to[e]]; s[cnt].v=to[e]; } sort(s+1,s+cnt+1,cmp); long long sum=1; for(long long i=1;i<=cnt;i++){ f[x]+=f[s[i].v]+sum; sum+=s[i].dis; } return ; } int main(){ n=rd(); for(long long i=1;i<=n;i++){ scanf("%s",x+1); len=strlen(x+1); pre(i); } dfs(1,0); dfss(0); printf("%lld",f[0]); return 0; }