洛谷 P1019 单词接龙【经典DFS,温习搜索】

P1019 单词接龙

题目描述

单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中出现两次),在两个单词相连时,其重合部分合为一部分,例如 beast和astonish,如果接成一条龙则变为beastonish,另外相邻的两部分不能存在包含关系,例如at 和 atide 间不能相连。

输入输出格式

输入格式:

输入的第一行为一个单独的整数n (n<=20)表示单词数,以下n 行每行有一个单词,输入的最后一行为一个单个字符,表示“龙”开头的字母。你可以假定以此字母开头的“龙”一定存在.

输出格式:

只需输出以此字母开头的最长的“龙”的长度

输入输出样例

输入样例#1:

5
at
touch
cheat
choose
tact
a

输出样例#1:

23           (连成的“龙”为atoucheatactactouchoose)   

说明

NOIp2000提高组第三题

题目链接:https://www.luogu.org/problem/show?pid=1019

分析:经典DFS,

思路:暴力枚举每一个以给定字母开头的字符串,然后开始搜索,在搜索判断是否相重的时候可以找出当前字符串(龙)的最后一个字符

然后再在将要比较的字符串里暴力找,如果能找到,再从当前位置往前找。如果直到将要比较的字符串全部比较完且全部相同,就加到龙里面

易错点:

1.可以无视题目中的at与atite的相互包含问题

2.不要忽视自身和自身相连的情况

3.注意龙和其长度和使用情况的初始值!!

4.注意+1-1的边界问题!!

详细注释在代码中已经给出,请参考代码

下面给出AC代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int n,used[20]={0},maxn=0; //n为单词数 used数组检测该单词是否已经被用多于两次(用++实现)  maxn表示最大长度
 4 string s[20],sum,x; //s字符串数组为读入单词 sum为各个情况最后所形成的龙 x为开头字母
 5 void dfs(string last)
 6 {
 7     if(last.size()==1)
 8         sum=last; //将开头字母看成上一个单词 用x初始化sum
 9     bool ans=0; //表示接下来是否有符合要求的单词
10     for(int i=0;i<n;i++)
11     {
12         if(used[i]<2)
13         {
14             int m; //m为相同字母个数
15             for(int j=last.size()-1;j>=0;j--)
16             { //从上一个单词的最后往前搜索
17                 if(last[j]==s[i][0])
18                 { //当该字母与当前单词首字母相同时
19                     m=1;
20                     ans=1; //有单词可接
21                     while(last[j+m]==s[i][m])
22                        m++; //记录相同字母数量
23                 }
24                 if(ans&&j+m==last.size())
25                     break; //若该字母加上相同字母数量等于原单词长度 该单词可接
26                 if(ans&&j+m!=last.size())
27                     ans=0; //若不等 则ans恢复为0(即可能只是在上一个单词的中间出现与下一个单词相同的部分)
28             }
29             if(ans)
30             {
31                 int len=sum.size();
32                 sum+=s[i].substr(m,s[i].size()-m); //在sum后面添加s[i]字符串第m(-1+1)个位置的s[i].size()-m个字符(下一个单词相同字母后的字母)
33                 used[i]++; //使用次数增加
34                 dfs(s[i]); //下一个单词搜索
35                 ans=0; //恢复
36                 used[i]--;
37                 sum.erase(len,s[i].size()-m); //删去sum中len位置起的s[i].size()-m个字符(恢复原单词)
38             }
39         }
40     }
41     if(!ans&&sum.size()>maxn)
42         maxn=sum.size(); //记录最大长度
43     return;
44 }
45 int main()
46 {
47     cin>>n;
48     for(int i=0;i<n;i++)
49         cin>>s[i];
50     cin>>x;
51     dfs(x);
52     cout<<maxn<<endl;
53     return 0;
54 }

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏数据结构与算法

BZOJ2212: [Poi2011]Tree Rotations(线段树合并)

可以证明,对于\(m\)个仅有一个元素,权值范围在\([1, n]\)的线段树合并的复杂度为\(mlogn\)

762
来自专栏一枝花算不算浪漫

HashMap中的hash算法总结

算法一直是我的弱项,然而面试中基本是必考的项目,刚好上次看到一个HashMap的面试题,今天也来学习下 HashMap中的hash算法是如何实现的。

3092
来自专栏大闲人柴毛毛

剑指 offer——面试题8求旋转数组的最小值

题目:将一个非递减序列的某一处切一刀,再把前半段序列放到后半段序列的后面,这样组成的新序列叫做“旋转数组”。要求获取一个旋转数组的最小值。 这本质上是一个求最值...

3476
来自专栏desperate633

LintCode 排颜色 II题目分析代码

给定一个有n个对象(包括k种不同的颜色,并按照1到k进行编号)的数组,将对象进行分类使相同颜色的对象相邻,并按照1,2,...k的顺序进行排序。

982
来自专栏数据结构与算法

26:统计满足条件的4位数个数

26:统计满足条件的4位数个数 总时间限制: 1000ms 内存限制: 65536kB描述 给定若干个四位数,求出其中满足以下条件的数的个数:  个位数上的...

4344
来自专栏一直在跳坑然后爬坑

RxJava2操作符之“Scan”作用示例用法运行结果分析总结

扫描,遍历,用法和上一个Reduce操作符差不多,只是这个操作符会将每一个过程的中间产物发射出来,而不是只发射结果

943
来自专栏用户画像

7.6.2 内部排序算法的应用

1)若n较小(N<=50),则可以采用直接插入排序或简单选择排序。由于直接插入排序所需的记录移动操作较简单选择排序多,因而当记录本身信息量较大时,用简单选择排序...

701
来自专栏java工会

java冒泡排序和快速排序

3043
来自专栏小小挖掘机

Numpy基础知识点汇总

1、概述 Numpy是高性能科学计算和数据分析的基础包,它的部分功能如下: 1)ndarray,一个具有矢量算术运算和复杂广播能力的快速且节省空间的多维数组。 ...

3174
来自专栏技术杂谈

给出一组非负整数,重新排序组成最大的数

先把对比的数字转成字符,拼接后再转成整数进行大小对比,即 int(a+b) 与 int(b+a) 进行降序排列。代码1。

6048

扫码关注云+社区

领取腾讯云代金券