C++-单词接龙 解题教程
【Horn Studio】编程专栏: 单词接龙 解题思路
题目
题目描述
单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中出现两次),在两个单词相连时,其重合部分合为一部分,例如beast和astonish,如果接成一条龙则变为beastonish,另外相邻的两部分不能存在包含关系,例如at和atide间不能相连。
输入
输入的第一行为一个单独的整数n(1<=n<=12)表示单词数,以下n行每行有一个单词(只含有大写或小写字母,长度不超过20),输入的最后一行为一个单个字符,表示“龙”开头的字母。你可以假定以此字母开头的“龙”一定存在。
输出
只需输出以此字母开头的最长的“龙”的长度。
样例输入 复制
5
at
touch
cheat
choose
tact
a
样例输出 复制
23
提示
连成的“龙”为atoucheatactactouchoose
来源
思路
对于这道题,有一个很好用的函数:substr——产生子串
返回一个新建的 初始化为string对象的子串的拷贝string对象。
子串是,在字符位置pos开始,跨越len个字符(或直到字符串的结尾,以先到者为准)对象的部分。
特别感谢 繁小华 提供了注解,原文链接:https://blog.csdn.net/sunshihua12829/article/details/50484966
拥有了这个,就是解决这道接龙题目的关键!
e.g:
4 3 2 1 4 3
2 1 5 6 √ 4 3 2 1 × 因为它包含了所有上一个字串
因此,最大截取限度为(n-1)
这道看似二级的题目,实则却拥有四级的dfs,笑里藏刀请注意!
代码
#include <bits/stdc++.h> using namespace std; int n,anslen = 0; string s[20]; int vis[1000000],k[20][20]; int csh(string x,string y){ int l1 = x.length(),l2 = y.length(); for (int i = 1;i <= min(l1,l2) - 1;i++){ if(x.substr(l1 - i,i) == y.substr(0,i)){ return i; } } return 0; } void dfs(int x,int len){ anslen = max(len,anslen); for (int i = 1;i <= n;i++){ if(vis[i] == 2 || k[x][i] == 0){ continue; } vis[i]++; dfs(i,len + s[i].length() - k[x][i]); vis[i]--; } } int main(){ scanf("%d",&n); for (int i = 1;i <= n+1;i++) cin>>s[i]; for (int i = 1;i <= n+1;i++){ for (int j = 1;j <= n+1;j++){ k[i][j] = csh(s[i],s[j]); } } for (int i = 1;i <=n;i++){ if(s[n+1][0] != s[i][0]){ continue; } vis[i]++; dfs(i,s[i].length()); vis[i]--; } printf("%d",anslen); return 0; }
彩蛋
:欸,我就不给dfs代码~