8783:单词接龙
-
总时间限制:
- 1000ms 内存限制:
- 65536kB
-
描述
-
单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中出现两次),在两个单词相连时,其重合部分合为一部分,例如beast和astonish,如果接成一条龙则变为beastonish,另外相邻的两部分不能存在包含关系,例如at和atide间不能相连。
输入 - 输入的第一行为一个单独的整数n(n<=20)表示单词数,以下n行每行有一个单词(只含有大写或小写字母,长度不超过20),输入的最后一行为一个单个字符,表示“龙”开头的字母。你可以假定以此字母开头的“龙”一定存在。 输出
- 只需输出以此字母开头的最长的“龙”的长度。 样例输入
-
5 at touch cheat choose tact a
样例输出 -
23
提示 - 连成的“龙”为atoucheatactactouchoose
- 分析:
- 看到题的第一眼我的反应时“我的天做得出来才有鬼”
- 然后我仔细看了看题,发现范围不大
- 既然如此,那么就用深搜把每个可能的匹配枚举出来
- 需要注意的是2个点:
- 一是如何连接单词,二是每个单词可以用两次
- 连接的时候一个字母一个字母地比对
- 单词用两次的话可以把输入复制一遍,然后n*2
- 代码加注释:
-
#include<cstdio> #include<cstring> char a[23][23]; int n,sum; bool vis[23]; bool lian(char a[],char b[]) { int la=strlen(a),lb=strlen(b),i,j,p; for(i=lb-1;i>0&&i>lb-la;i--) if(b[i]==a[0]) { for(j=i+1;j<lb;j++) if(b[j]!=a[j-i]) goto he; for(j=lb,p=lb-i;p<la;p++,j++) b[j]=a[p];//连接 return 1; he:; } return 0;//不能连接 } void xmy(int s,char k[]) { char o[410]; for(int j=0;j<n;j++) if(!vis[j]) { memset(o,0,sizeof(o));//之所以要用o数组是因为函数调用的时候数组传的是地址 //也就是说后面的改动会影响k的值,因为它们对应同一地址 strcpy(o,k); if(lian(a[j],o)) {vis[j]=1;xmy(strlen(o),o);vis[j]=0;} else if(j%2==0) j++;//如果当前的这个单词不能连接,那么它所复制的单词也不能连接,这是优化 //if(j%2==0)非常重要,因为如果当前单词已经是复制出来的就不用加了,当初我没写。。。。卡了老半天 } if(s>sum) sum=s; } int main() { scanf("%d",&n);n*=2; for(int i=0;i<n;i+=2) { scanf("%s",a[i]); strcpy(a[i+1],a[i]);//复制一遍 } char k[1]; scanf("%s",k); for(int i=0;i<n;i+=2)//+2,因为同一个单词拓展出的是一样的 if(k[0]==a[i][0]) {vis[i]=1;xmy(strlen(a[i]),a[i]);vis[i]=0;} printf("%d",sum); }