题目描述
Description
给出了N个单词,已经按长度排好了序。如果某单词i是某单词j的前缀,i->j算一次接龙(两个相同的单词不能算接龙)。
你的任务是:对于输入的单词,找出最长的龙。
输入描述
Input Description
第一行为N(1<=N<=105)。以下N行每行一个单词(由小写组成),已经按长度排序。(每个单词长度<50)
输出描述
Output Description
仅一个数,为最长的龙的长度。
样例输入
Sample Input
5
i
a
int
able
inter
样例输出
Sample Output
3
数据范围及提示
Data Size & Hint
1<=N<=10^5
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
/* 看到题目输入为按长度排序才有的想法,因为这样能使比i单词 字典序小的单词都在i的前面,所以扫描一遍单词进行dfs插入 形成一棵根节点为0的树,使以i为前缀的单词为i的子节点, 最后再dfs一边求树的深度即可。 */ #include<cstdio> #include<iostream> #include<cstring> #include<vector> #define M 100010 using namespace std; char ch[M][60]; int n,len[M],flag,ans; vector<int> grap[M]; bool ok(int pos,int x) { if(len[pos]>=len[x])return false; for(int i=0;i<len[pos];i++) if(ch[pos][i]!=ch[x][i]) return false; return true; } void insert(int pos,int x) { if(flag)return; for(int i=0;i<grap[pos].size();i++) if(ok(grap[pos][i],x)) { insert(grap[pos][i],x); return; } if(!flag) { grap[pos].push_back(x); flag=1; return; } } void dfs(int pos,int t) { ans=max(ans,t); for(int i=0;i<grap[pos].size();i++) dfs(grap[pos][i],t+1); } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { cin>>ch[i]; len[i]=strlen(ch[i]); } for(int i=1;i<=n;i++) { flag=0; insert(0,i); } dfs(0,0); printf("%d",ans); return 0; }