题目描述
单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中出现两次),在两个单词相连时,其重合部分合为一部分,例如 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