【JZOJ5040】【NOI2017模拟4.2】押韵
2017-04-06 16:01
204 查看
Description
小A非常喜欢所有押韵的东西,他认为两个单词押韵当且仅当他们的公共后缀的长度和两个单词中最长的单词的长度相等,或者是最长的单词的长度减一。也就是说LCS(A,B)>=max(|A|,|B|)-1。有一天,小A读了一个有N个单词的小故事,他想知道,如果挑选一些故事里出现的单词组成一个新的单词序列,能组成的最长的满足以下条件的单词序列的长度是多少:单词序列中任意相邻的两个单词都押韵。(每个单词最多只能用一次)(1<=N<=500000)
Solution
这是一道挺水的题。显然我们要倒着建一棵字典树。对于字典树上的一个点x,我们可以在以x儿子y为根的子树中找一条最长链并加上y的其他兄弟构成x的最长链。那答案就是点x的儿子的最长链+次长链+点x的其他儿子数量。
Code
#include<iostream> #include<cmath> #include<cstring> #include<cstdio> #include<algorithm> using namespace std; const int maxn=2300000; int f[maxn][26],d[maxn],g[maxn]; int n,i,t,j,k,l,x,y,z,ans,num; char s[maxn]; int main(){ freopen("rhyme.in","r",stdin);freopen("rhyme.out","w",stdout); scanf("%d\n",&n); for (i=1;i<=n;i++){ scanf("%s\n",s+1); x=0;t=strlen(s+1); for (j=t;j>=1;j--){ if (!f[x][s[j]-97]) f[x][s[j]-97]=++num; x=f[x][s[j]-97]; } d[x]++; } for (x=num;x>=0;x--){ t=k=0;g[x]=d[x]; for (j=0;j<26;j++){ if (!d[f[x][j]])continue; g[x]++; if (t<g[f[x][j]]-1)k=t,t=g[f[x][j]]-1; else if (k<g[f[x][j]]-1) k=g[f[x][j]]-1; }l=t; if (k){ t=t+k; ans=max(ans,t+g[x]); } g[x]+=l;ans=max(ans,g[x]); } printf("%d\n",ans); }
相关文章推荐
- 【NOI2017模拟4.2】押韵
- 【JZOJ5039】【NOI2017模拟4.2】查询
- [JZOJ5029]. 【NOI2017模拟3.25】围墙
- 【JZOJ5037】【NOI2017模拟3.30】轮回
- JZOJ 5043. 【NOI2017模拟4.4】保持平衡
- 【NOI2017模拟4.2】查询【线段树】
- 【JZOJ 100019】【NOI2017模拟6.26】A
- jzoj5043 【NOI2017模拟4.4】保持平衡 (可撤销贪心)
- 【JZOJ5045】【NOI2017模拟4.5】无限棋盘
- [JZOJ5044]【NOI2017模拟4.4】Sone0
- 【JZOJ5180】【NOI2017模拟6.29】呵呵
- JZOJ 100019【NOI2017模拟6.26】A
- [JZOJ100019] 【NOI2017模拟6.26】A
- 【JZOJ5037】【NOI2017模拟3.30】轮回
- 【JZOJ5046】【NOI2017模拟4.5】机器人游戏
- [JZOJ100003]【NOI2017模拟.4.1】 Tree
- 【JZOJ5043】【NOI2017模拟4.4】保持平衡
- [JZOJ5036]【NOI2017模拟3.30】原谅
- [JZOJ100004]【NOI2017模拟.4.1】 Dice
- 【NOI2017模拟4.2】查询