文章目录
- 题目链接
- 题目描述
- 解题思路
- 代码实现
- 总结
题目链接
链接: P1019 [NOIP2000 提高组] 单词接龙
题目描述
解题思路
这是一道深度优先搜索题目,我们定义check函数来计算两个字符串的最小重合部分,dfs中第一个参数代表我们当前使用的是哪一个字串,不需要是拼接后的字符串,因为他没让我们输出最后的字符串,只是要最后字符串的长度,第二个参数则是当前拼接字符串的长度
下面来看dfs代码
这段代码是更新答案
ans=max(ans,l);
下面这段代码是dfs的主体,因为每个子串只能使用2次,所以我们定义一个fre即使用频率数组,如果使用次数已经大于等于两次,则不考虑这个子串,continue,之后要注意先检查重合部分是否大于0,之后别忘记回溯
for(int i=0;i<n;i++){if(fre[i]>=2) continue;if(check(now,s[i])){fre[i]++;dfs(s[i],l+s[i].length()-check(now,s[i]));fre[i]--;}}
最后一个需要注意的点是因为字符串之间不能存在包含关系,如果只传递s[n],则不会拼接,最后的结果就是原本的子串长度,为1
所以要在前面加一个空白字符
dfs(' '+s[n],1);
代码实现
#include<bits/stdc++.h>
using namespace std;
string s[20];
int fre[20],n,ans=0;
int check(string a,string b)
{for(int i=1;i<min(a.length(),b.length());i++){bool flag=true;for(int j=0;j<i;j++){if(a[a.length()-i+j]!=b[j]){flag=false;break;}}if(flag) return i;}return 0;
}
void dfs(string now,int l)
{ans=max(ans,l);for(int i=0;i<n;i++){if(fre[i]>=2) continue;if(check(now,s[i])){fre[i]++;dfs(s[i],l+s[i].length()-check(now,s[i]));fre[i]--;}}
}
int main()
{cin>>n;for(int i=0;i<=n;i++) cin>>s[i];dfs(' '+s[n],1);cout<<ans;return 0;
}
总结
这是一道经典的深度优先搜索(DFS)题目,要求找出单词接龙的最长长度。首先通过check函数计算两个字符串的最小重合部分,然后通过DFS算法来实现遍历所有可能的接龙方式,并更新最长长度。代码实现中使用了适当的剪枝来减少搜索空间和优化算法效率。