题目描述
单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中出现两次),在两个单词相连时,其重合部分合为一部分,例如 beastbeastbeast和astonishastonishastonish,如果接成一条龙则变为beastonishbeastonishbeastonish,另外相邻的两部分不能存在包含关系,例如atatat 和 atideatideatide 间不能相连。
嗯...
嗯嗯...
嗯嗯嗯...
挠头苦想一下午没改出来却被c老一语道破天机的我感觉自己好tm**啊...
哎,算了算了
反正硕大一个天七就我两年都爆零了呸我啥也没说
来好好捋一捋这道题算了
学过搜索的都知道,这道题就是dfs,简简单单的dfs
因为只有20个单词,所以不需要任何优化
先判断能不能接上,能接上就dfs下去,然后每次更新龙的长度
但为什莫我没做出来呢?
先上代码吧:
#include<bits/stdc++.h> using namespace std; string a[10000];//单词 int use[10000];//判断用的次数 int num;//单词的个数 int maxn=-2;//储存龙的长度 int f(string s,string b)//用于计算龙和单词之间的重合长度 { if(b.find(s)!=-1) return -2;//题目要求:相邻的两部分不能存在包含关系 int l=b.find(s[s.size()-1]); //举个例子: //abc bc从bc的c开始,倒着往回判断 int gg=l; int m=s.size()-1; int flag=1; if(l==-1) return 0;//无重叠?再见了您嘞~ else { while(l>=0) { if(b[l]!=s[m])//倒着判断 { flag--; break; } l--; m--; } if(flag==1) return gg+1;//尾部吻合,OK! } return -2;//不吻合,再见! } void c(string q,int d)//dfs函数 { maxn=max(maxn,d);//更新龙的长度 for(int i=0;i<num;i++) { if(f(q,a[i])>0&&use[i]<=1)//首先尾部要吻合;其次,单词要没用过或只用了一次 { use[i]++;//标记用过 c(q+a[i],d+a[i].size()-f(q,a[i]));//dfs use[i]--;//不起眼但十分重要的回溯 } } } int main(void)//rxz:没啥用,但这是个好习惯~(哼) { cin>>num; string uu; for(int i=0;i<=num;i++) { cin>>a[i];//输入单词 } uu=' '+a[num];//强制重叠函数比较最后一位 c(uu,1);//长度已经是1了 cout<<maxn; //cin>>a[0]>>a[1];用于检查 //cout<<f(a[0],a[1]); 用于检查 return 0; }
题目很短,但信息不少。
有这样一句话:
另外相邻的两部分不能存在包含关系,例如atatat 和 atideatideatide 间不能相连
就这样,我犯了第一个智障错误:
没特判包容情况!!!
改一改:
if(b.find(s)!=-1) return -2;//题目要求:相邻的两部分不能存在包含关系
改完之后,信心满满,提交!
额,咋全WA了...
经过C老的点拨,我又发现了自己的错误:
while(l>=0) { if(b[l]!=s[m])//倒着判断 { flag--; break; } l--; m--; }
原来我while里写的是>,但是当l等于1时循环就会停止。像abc ac 这一组数据就会出现判断失误
再三改正,历经磨难,终于AC
沉痛反思:
1.读题仔细,找出题目中可能存在的特殊条件,并在代码中实现。
2.在第一次打运算符时,一定要谨慎,打不打等号,一定要有一个清晰的概念,模凌两可会有很高的风险
3.打注释,方便检查,可以节省出大量的时间
完结撒花~
来源:https://www.cnblogs.com/zhangzhiyuan123/p/12285248.html