词链
来源:互联网 发布:windows不能切换到mac 编辑:程序博客网 时间:2024/05/21 00:45
【题目描述】
给定一个仅包含小写字母的英文单词表,其中每个单词最多包含50个字母。
如果一张由一个词或多个词组成的表中,每个单词(除了最后一个)都是排在它后面的单词的前缀,则称此表为一个词链。例如下面的单词组成了一个词链:
i
int
integer
而下面的单词不组成词链:
integer
intern
请在给定的单词表中取出一些词,组成最长的词链。最长的词链就是包含单词数最多的词链。
数据保证给定的单词表中,单词互不相同,并且单词按字典顺序排列。
【输入格式】
第一行一个整数n(n<=100000),表示单词表中单词数
下接n行每行一个单词。
【输出格式】
一个整数,表示最长词链长度。
【样例输入】
5iintintegerinterninternet
【输出格式】
4
【分析】
这题可以用多种方法做!
首先是暴力算法,复杂度
#include<bits/stdc++.h>using namespace std;const int N=3005;int f[N];char a[N][55];int main(){ int n; scanf("%d",&n); for (int i=1;i<=n;i++) scanf("%s",a[i]); f[1]=strlen(a[1]); for (int i=2;i<=n;i++) for (int j=1;j<i;j++){ if (strlen(a[i])<=strlen(a[j])) continue; int flag=1; for (int k=0;k<strlen(a[j]);k++) if (a[i][k]!=a[j][k]) {flag=0;break;} if (flag) f[i]=max(f[i],f[j]+1); } int ans=0; for (int i=1;i<=n;i++) ans=max(ans,f[i]); cout<<ans;}
方法1:用栈维护,最后输出栈的最大深度即可。因为题目已经按字典序排好,所以这种方法的正确性也就不难证明了。
#include<bits/stdc++.h>using namespace std;const int N=100005;char st[N][55],a[N][55];int judge(char* s1,char* s2){ int n=strlen(s1),m=strlen(s2); while (s1[n-1]==' ') n--; for (int i=0;i<n&&i<m;i++) if (s1[i]!=s2[i]) return 0; return 1;}int main(){ int n,ans=1; scanf("%d",&n); for (int i=1;i<=n;i++) scanf("%s",a[i]); int top=1; for (int i=0;i<strlen(a[1]);i++) st[1][i]=a[1][i]; for (int i=2;i<=n;i++){ if (judge(st[top],a[i])){ top++; for (int j=0;j<strlen(a[i]);j++) st[top][j]=a[i][j]; } else{ while(!judge(st[top],a[i])){ for (int j=0;j<strlen(st[top]);j++) st[top][j]=' '; top--; } top++; for (int j=0;j<strlen(a[i]);j++) st[top][j]=a[i][j]; } ans=max(ans,top); } cout<<ans;}
方法2:极其明显的字典树啊,把每个字符看成是树的一个节点,然后读进来一个就加到树里,维护即可。
#include<stdio.h>#include<string.h>#include<algorithm>#include<iostream>using namespace std;#define maxn 51*100000struct list{ int id,num; struct list *next[27];}*root;int ans;struct list *build(){ int i; struct list *p; p=new list; p->id=0; p->num=0; for(i=0;i<27;i++) p->next[i]=0; return p;}void query(char str[]){ int mn; mn=0; struct list *p; p=root; int n,j; n=strlen(str); for(j=0;j<n;j++){ int c=str[j]-'a'; if(p->next[c]==NULL) p->next[c]=build(); p=p->next[c]; mn=max(mn,p->num); } p->num=mn+1; ans=max(ans,mn+1);}int main(){ int n,i; char str[101]; scanf("%d",&n); ans=0; root=build(); for(i=0;i<n;i++){ scanf("%s",str); query(str); } printf("%d\n",ans);}
方法3:Hash胡乱搞,把枚举前1~i-1个字符串的过程优化下,这里就不写代码了(并不会写)。
方法4:参考“拦截导弹”一题,用最长上升子序列的二分算法做,注意拦截导弹那题是比较两个数,这题是比较两个字符串,反正我码力太渣写不对觉得代码比较复杂容易写错,而且复杂度跟前面的几个算法相比也不是很理想,所以不推荐这个思路(然而这是我第二个思路,第一个是字典树)。
阅读全文
1 0
- 词链
- 词链
- 【动态规划】【RQ429】词链
- rqnoj-429词链
- 【Trie】【cogs173】词链
- 【洛谷 P1127】词链
- RQNOJ 429 词链
- rqnoj-429词链-字典树
- ACM 173. 词链(单调堆栈)
- RQNOJ LIS专题 201奥运大包围,569Milking Time,429词链
- SOA治理系统中mvn版本号管理经验总结
- Linux C进程总结(下)
- python readline
- 关于DIP,IoC,DI,以及IoC容器的一个说明
- 深度神经网络
- 词链
- 平衡二叉树/镜像
- C
- hibernate的主键增长策略
- dhcp服务
- CentOS7上安装和使用Docker
- JavaSE面向对象多态中关于被static修饰的方法不存在被重写
- 第一篇文章不应该是hello world, 而是怎么使用markdowm
- 算法面试题之好多鱼