AcWing
  • 首页
  • 课程
  • 题库
  • 更多
    • 竞赛
    • 题解
    • 分享
    • 问答
    • 应用
    • 校园
  • 关闭
    历史记录
    清除记录
    猜你想搜
    AcWing热点
  • App
  • 登录/注册

1019单词接龙

作者: 作者的头像   cccccccup ,  2025-05-10 15:33:47 · 福建 ,  所有人可见 ,  阅读 2


0


题目

微信截图_20250510151937.png

易错点

思维盲区(也是对dfs的不熟悉)

在dfs中,比如有多个可能都可以符合当前递归的要求,那就把所有范围都遍历一遍,用if作为条件判断,如果成立,在真正地进行递归
也就是在dfs里出现for循环,依次遍历每个可能的方案,并用if进行条件筛选
不用担心不成立怎么办,因为代码的写法会让不成立的逐个扫描过去,如果无路可走,就会直接回溯

本题中有两处地方都是这样的:
1、对于当前字符串x后所要连接的字符串,所有字符串s[i]都有可能,那就对所有字符串s进行遍历。再用if进行判断

微信截图_20250510152747.png

2、刚开始第一次调用dfs时,只要是首字母和所给出的字母一样的,都可能作为首单词,因此遍历所有的字符串,只要能作为首单词,就进行深度搜索
微信截图_20250510152758.png

3、最大值就是在多种可能的深搜中,一次次取max得到所有情况里的最大值

总结:
深搜的本质依旧是搜索,所以遍历所有可能情况是再正常不过的事情。
特殊就特殊在是“深”,因为一旦当前某种选择成立了,我们就在这之下继续调用dfs搜索下去。

对“相邻的两部分不能存在包含关系”的错误思考

微信图片_20250510152542.jpg

因此要保证不会出现这两种情况
只需让j<x.size()&&j<s[i].size()

如何判断字符串A和字符串B能否相接

从小到大枚举相同部分的长度,一旦找到相等的,就break。因为这时候就是最小的公共前后长度,取最小的,能保证连出来的是最长的
使用substr取出子串,然后判断是否相等

    int len=x.size();
    for(int j=1;j<x.size()&&j<s[i].size();j++){
        if(x.substr(x.size()-j,j)==s[i].substr(0,j)){
            len=j;
            break;//从小到大,找到相等的。这时候就是最小的公共前后长度,取最小的,能保证连出来的是最长的
        }
    }
    if(len<x.size()&&len<s[i].size()){
        //说明两个串没有重合且拥有前后相等部分,能选
        t+=s[i].size()-len;
        use[i]++;
        dfs(s[i]);
        t-=s[i].size()-len;
        use[i]--;
    }

没有初始化导致的严重错误

一开始我写的是int len;
没有初始化
导致多次运行同一样例,竟然出现了不同的结果
如果没给len初始化时赋值,会导致如果下面for没成立,len的值就一直等于随机值,造成后文对len的判断错误!!!!

什么东西必须记录,什么东西没必要记录要弄清楚

比如本题最后要输出的就是一个最大长度
那根本没必要存下来整个穿在一起的字符串
直接存当前已经串出来的长度就好了

#include <bits/stdc++.h>
using namespace std;

const int N=25;

int n;
string s[N];
int use[N];
int t;//每次当前已经连接的字符串长度,只记下长度,不记总的连的字符串的内容
int ans;

void dfs(string x)
{
    ans=max(ans,t);//先对ans和当前长度t取个最大值
    //找出能连在x后面的(只要能连,就遍历,反正有max取最大值)
    for(int i=0;i<n;i++){
        if(use[i]<2){
            int len=x.size();//我这里一开始没给len赋值,导致如果下面for没成立,len的值就一直等于随机值,造成后文对len的判断错误!!!!
            for(int j=1;j<x.size()&&j<s[i].size();j++){
                if(x.substr(x.size()-j,j)==s[i].substr(0,j)){
                    len=j;
                    break;//从小到大,找到相等的。这时候就是最小的公共前后长度,取最小的,能保证连出来的是最长的
                }
            }
            if(len<x.size()&&len<s[i].size()){
                //说明两个串没有重合且拥有前后相等部分,能选
                t+=s[i].size()-len;
                use[i]++;
                dfs(s[i]);
                t-=s[i].size()-len;
                use[i]--;
            }
        }
    }

}

int main()
{
    scanf("%d",&n);
    for(int i=0;i<n;i++)  cin>>s[i];

    //易错点 
    //不要用 scanf("%c",...) 很容易错! 因为会读取换行符,空格符等 
    //char beg;scanf("%c",&beg);

    char beg[2];scanf("%s",beg);//改成使用scanf("%s",...)输入到char数组,然后使用char[0] 
    for(int i=0;i<n;i++){//每个符合要求的字符串都试试作为起始串
        if(s[i][0]==beg[0]){
            use[i]++;
            t=s[i].size();
            dfs(s[i]);
            use[i]--;
        }
    }
    printf("%d\n",ans);
    return 0;
}

0 评论

App 内打开
你确定删除吗?
1024
x

© 2018-2025 AcWing 版权所有  |  京ICP备2021015969号-2
用户协议  |  隐私政策  |  常见问题  |  联系我们
AcWing
请输入登录信息
更多登录方式: 微信图标 qq图标 qq图标
请输入绑定的邮箱地址
请输入注册信息