当前位置: 首页 > news >正文

单词接龙--蒟蒻解析

我是觉得这道题目巨难,所以认真写了一篇博客,也可能是我是蒟蒻的原因吧

​​​​​​​P1019 [NOIP 2000 提高组] 单词接龙 - 洛谷https://www.luogu.com.cn/problem/P1019

题目说每个单词只能用两次,所以我们直接将这组单词复制一次,弄成两组相同的单词,然后在比较前后缀相同的东西,根据这个写了一个check函数,进行对比,并且我增加了点难度,把23位的龙打印了出来,写出来,我觉得还是很有成就感的吧!!!

 

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

// 全局变量声明
int n, ans;            // n: 初始字符串数量,ans: 记录最长龙的长度
char ch;               // 龙头字符要求
string s[42], str, ret;// s: 字符串数组(含副本),ret: 存储最长龙
int vis[42];           // 访问标记数组,控制每个字符串最多使用两次

/* 检查两个字符串的重叠部分
 * s1: 已拼接的字符串
 * s2: 待拼接的字符串
 * 返回: 最大重叠长度,无重叠返回-1 */
int check(string s1, string s2) {
    // 从s1末尾开始尝试匹配,寻找最大重叠
    for (int i = s1.length() - 1; i >= 0; i--) {
        int len = s1.length() - i; // 当前尝试的重叠长度
        // 截取s1末尾len长度与s2开头len长度比较
        if (s1.substr(i) == s2.substr(0, len)) {
            return len; // 返回实际重叠长度
        }
    }
    return -1;
}

/* 深度优先搜索构建单词龙
 * q: 当前拼接的字符串
 * dep: 递归深度(已使用的字符串数量)*/
void dfs(string q, int dep) {
    // 更新最长记录
    if (q.length() > ans) {
        ans = q.length();
        ret = q;
    }
    
    // 终止条件:每个字符串最多使用两次(总深度2n)
    if (dep > 2 * n) return;

    // 遍历所有字符串(包含副本)
    for (int i = 1; i <= 2 * n; i++) {
        // 第一层特殊处理:必须匹配龙头字符
        if (dep == 1 && !vis[i] && ch == s[i][0]) {
            vis[i] = 1;
            dfs(q + s[i], dep + 1); // 拼接新字符串
            vis[i] = 0;             // 回溯
        }
        // 后续层处理:需要满足重叠条件
        else if (dep >= 2 && !vis[i]) {
            int res = check(q, s[i]);
            if (res != -1) {        // 存在有效重叠
                vis[i] = 1;
                // 拼接时跳过重叠部分
                dfs(q + s[i].substr(res), dep + 1);
                vis[i] = 0;         // 回溯
            }
        }
    }
}

int main() {
    // 输入处理
    cin >> n;
    for (int i = 1; i <= n; i++) cin >> s[i];
    // 创建字符串副本(允许每个字符串使用两次)
    for (int i = n+1; i <= 2*n; i++) s[i] = s[i - n];
    cin >> ch;  // 输入龙头字符
    
    dfs(str, 1); // 从空字符串开始搜索
    cout<<ret<<ans//以防止有人抄袭,我将这个打印出来了
    cout << ans; // 输出最大长度
    return 0;
}

 还有一种方法,就是用used标记两个数组,最多只能用两个,超过不行

#include<bits/stdc++.h>
using namespace std;
int n,ans;
string str[30];
int used[30];
int check(string a,string b) {
	int la = a.length();
	int lb = b.length();
	int l = min(la, lb);
	for (int i = 1; i < l; i++) {
		int flag = 1;
		for (int j = 0; j < i; j++) {
			if (a[la - i + j] != b[j])flag = 0;
		}
		if (flag)return i;
	}
	return 0;
}
void dfs(string s, int len) {
	ans = max(ans, len);

	for (int i = 1; i <= n; i++) {
		if (used[i] >= 2)continue;
		int c = check(s, str[i]);
		if (c > 0)
		{
			used[i]++;
			dfs(str[i], len + str[i].length() - c);
			used[i]--;
		}
	}
}
int main() {
	cin >> n;
	for (int i = 1; i <= n; i++)
	{
		cin >> str[i];
	}
	string S;
	cin >> S;
	dfs(' '+S, 1);
	cout << S << endl;
	cout << ans << endl;
	return	0;
}

相关文章:

  • 【够用就好005】-在VSCode中管理ECS服务器的实操步骤
  • 基于ros2与gazebo的导航仿真案例
  • 在 Flutter 中实现文件读写
  • 51单片机-8X8LED点阵
  • 01背包,完全背包,多重背包
  • vue,vue3 keepalive没有效果,无法缓存页面include无效,keep-alive
  • 【Git】五、多人协作
  • 鸿蒙-自定义相机拍照
  • 了解string
  • Apache Spark 的主要特点
  • 工厂车辆排队系统
  • 关于解决springcloud 创建bean失败的问题
  • 【python】解析自动化脚本文件并按照=测试周期=存储记录
  • react hook useReducer
  • 如何解决服务器被黑客爬虫攻击:全面防护与优化策略
  • Android TabLayout 实现随意控制item之间的间距
  • rk3588/3576板端编译程序无法运行视频推理
  • vue-element-admin 打包部署到SpringBoot
  • Linux Python 调试/堵塞/性能分析与定位工具
  • 【Cesium学习(十三)】Cesium学习主要优秀资源资料总结
  • 贯彻落实《生态环境保护督察工作条例》,充分发挥生态环境保护督察利剑作用
  • 当“诈骗诱饵”盯上短剧
  • 第十一届世界雷达展开幕,尖端装备、“大国重器”集中亮相
  • 第十届曹禺剧本奖上海揭晓,首次开放个人申报渠道
  • 老字号“逆生长”,上海制造的出海“蜜”钥
  • 泽连斯基:乌代表团已启程,谈判可能于今晚或明天举行