P1368 【模板】最小表示法(SAM 求最小循环移位)

该文描述了一种基于Minecraft游戏背景的问题,玩家需要重组由方块组成的工艺品,目标是最小化瑕疵度。通过建立字符串模型,问题转化为寻找字典序最小的循环移位。文章提出使用后缀自动机(SAM)构建长度为2n的新串,并通过贪心策略找到最优解,时间复杂度为O(n)。

【模板】最小表示法

题目描述

小敏和小燕是一对好朋友。

他们正在玩一种神奇的游戏,叫 Minecraft。

他们现在要做一个由方块构成的长条工艺品。但是方块现在是乱的,而且由于机器的要求,他们只能做到把这个工艺品最左边的方块放到最右边。

他们想,在仅这一个操作下,最漂亮的工艺品能多漂亮。

两个工艺品美观的比较方法是,从头开始比较,如果第 iii 个位置上方块不一样那么谁的瑕疵度小,那么谁就更漂亮,如果一样那么继续比较第 i+1i+1i+1 个方块。如果全都一样,那么这两个工艺品就一样漂亮。

输入格式

第一行一个整数 nnn,代表方块的数目。

第二行 nnn 个整数,每个整数按从左到右的顺序输出方块瑕疵度的值。

输出格式

一行 nnn 个整数,代表最美观工艺品从左到右瑕疵度的值。

样例 #1

样例输入 #1

10
10 9 8 7 6 5 4 3 2 1

样例输出 #1

1 10 9 8 7 6 5 4 3 2

提示

  • 对于 20%20\%20% 的数据,n≤1000n\le 1000n1000
  • 对于 40%40\%40% 的数据,n≤104n\le 10^4n104
  • 对于 100%100\%100% 的数据,n≤3×105n\le 3\times 10^5n3×105

题意:

虽然题目给定的是个数组,但我们可以把问题抽象成:给定一个长度为 n 的字符串 s,找出字典序最小的循环移位(长度也为 n)。以下的分析我们均用 “串” 来代替数组。

思路:

SAM 高度压缩了原串各种长度的所有子串。我们发现:字符串 s + s 包含 s 的所有循环移位作为子串。所以如果要找字典序的最小循环移位,不妨将原串复制一份,形成一个长度为 2n 的串,选择所有长度为 n 的子串集合中字典序最小的那个

我们对长度为 2n 的新串构建后缀自动机,从DAG的根节点开始,每次贪心的走字典序最小的节点,走 n 步,边走边输出即可。

时间复杂度:O(n)O(n)O(n)

代码:

#include<bits/stdc++.h>

using namespace std;

const int N = 6e5 + 10, M = N << 1;
int n, a[N], len[M], fa[M], np = 1, tot = 1;
map<int, int> ch[M];
vector<int> g[M];

void extend(int c)
{
	int p = np; np = ++tot;
	len[np] = len[p] + 1;
	while (p && !ch[p][c]) {
		ch[p][c] = np;
		p = fa[p];
	}
	if (!p) {
		fa[np] = 1;
	}
	else {
		int q = ch[p][c];
		if (len[q] == len[p] + 1) {
			fa[np] = q;
		}
		else {
			int nq = ++tot;
			len[nq] = len[p] + 1;
			fa[nq] = fa[q], fa[q] = fa[np] = nq;
			while (p && ch[p][c] == q) {
				ch[p][c] = nq;
				p = fa[p];
			}
			ch[nq] = ch[q];
		}
	}
}

signed main()
{
	scanf("%d", &n);
	for (int i = 0; i < n; ++i) {
		scanf("%d", &a[i]);
		a[i + n] = a[i];
	}
	n <<= 1;
	for (int i = 0; i < n; ++i) {
		extend(a[i]);
	}
	int p = 1;
	for (int i = 0; i < n / 2; ++i) {
		auto pp = ch[p].begin();	//由于map自动按第一关键字排序,因此每次贪心地选择首元素走就行
		int ele = (*pp).first;
		int nd = (*pp).second;
		printf("%d ", ele);
		p = nd;
	}
	puts("");

	return 0;
}
软件思维能力工程实训 I 课程设计要 二零二五年六月仓储管理课程设计 仓储管理课程设计功能介绍 1. 登录(Login) (1) 功能描述:允许用户通过用户名和密码登录系统,以及提供用户注册的功能。 (2) 详细内容: 1 用户输入用户名和密码。 2 系统验证用户名和密码是否正确。 3 如果验证失败,提示用户“用户名或密码错误”,并允许重新输入。 4 根据第二项功能(加解密)完成用户注册,提示注册用户输入密码以及确认密码 (校验两次密码的输入是否一致,一致后加密存储到用户信息表中,并重新跳转到系统登 录页) 5 在本地以 txt 文本维护一个用户信息表,将用户密码进行本地持久化存储。 2. 加解密(Encryption and Decryption) (1) 功能描述:用户登录提供简单的加密和解密功能,用于保护敏感信息,如用户名和密码。 (2) 详细内容: 1 加密算法:使用凯撒加密算法(Caesar Cipher),将每个字母在字母表中向前或向后 移 动固定数量的位置,以移动 3 位举例: a. 加密:A -> D,B -> E,C -> F,……,X -> A,Y -> B,Z -> C。 b. 解密:D -> A,E -> B,F -> C,……,A -> X,B -> Y,C -> Z。 c. 对于数字和符号,可以保持不变或进行类似的偏移操作。 2 采用加盐的思想进一步提高密码安全性:使用 random 包生成一个随机的盐值,然后 将盐 值和加密后的密码再次进行凯撒加密。 3 加密和解密流程 a. 加密流程: 1) 使用凯撒加密算法对用户密码进行加密。 2) 生成一个随机的 16 位盐值。(使用 random 包生成一个 16 位字符串 ) 3) 将盐值和加密后的密码拼接起来。 4) 再次使用凯撒加密算法对拼接后的字符串进行加密。b. 解密流程: 1) 使用凯撒解密算法对加密后的字符串进行解密。 2) 提取盐值部分。 3) 使用凯撒解密算法对剩余部分进行解密,剔除盐值,得到原始密码。 3. 库存查询(Inventory Query) (1) 功能描述:查询库存中的商品信息。 (2) 详细内容: 1 精确查询:通过商品编号字段进行精确查询。 2 模糊查询:输入商品名称的一部分或关键词,查询所有匹配的商品。 3 库存数量查询:查询库存数量在指定范围内的商品。 4 显示信息:查询结果包括商品编号、名称、商品种类名称、库存数量、供应商名称。 4. 入库操作(Inventory Inbound) (1) 功能描述:记录商品入库的信息,并更新库存。 (2) 详细内容: 1 输入商品编号、进货数量、供应商信息。 2 系统检查商品编号是否重复,若重复则提示错误。 3 若商品编号不存在则自动创建商品,同时使用户设置商品信息,并校验参数是否合法, 合 法才可创建。 (商品信息为:商品名称,商品种类名称和供应商名称,但是商品种类与供应商要与 category _info 和 supplier_info 一致) 4 检查通过后,根据进货数量更新库存数量,获取当前进货日期用于记录。 (进货日期示例:2025-6-5) 5 记录入库记录,包括入库的商品编号、本次进货数量、库存数量、进货日期、供应商 和当 前入库时间。 (入库时间示例:2025-6-5 14:11:23)。 6 自动生成入库单以向用户展示,包含入库商品的详细信息 7 通过 txt 文本将入库单存储到本地进而实现持久化存储。 5. 出库操作(Inventory Outbound) (1) 功能描述:记录商品出库的信息,并更新库存(2) 详细内容: 1 输入商品编号、出库数量和备注信息(用于记录出库用途)。 2 系统检查库存数量是否足够,若不足则提示“库存不足”。 3 检查足够后系统自动更新库存数量,减少出库数量。 4 记录出库记录,包括出库的商品编号、出库数量、出库时间和备注信息。 (出库时间示例:2025-6-5 14:11:23) 5 自动生成出库单以向用户展示,提供查看出库商品的详细信息的功能。 (商品详细信息为:商品编号、名称、商品种类、库存数量、供应商) 6 通过 txt 文本将出库单存储到本地进而实现持久化存储。 6. 手动信息更新(Inventory Update) (1) 功能描述:对仓储数据进行添加或更新,添加或修改供货商、商品种类、商品基本信息。 (2) 详细内容: 1 对 category _info、supplier_info 和 product_info 三张表进行维护与更新。 2 添加或修改供货商、商品种类、商品的基本信息以及库存数量。(判断参数是否合法) 3 直接调整库存数量(适用于盘点后发现库存数量与系统记录不符的情况)。 4 对输入的数据进行参数校验,检查输入的数据是否合法,合法才可进行库存的更新。 (考虑商品编号是否存在、价格和数量的数据是否为正数,可在此基础上进行更多的参数 校验)7. 库存盘点(Inventory Audit) (1) 功能描述:展示所有商品的库存情况,并根据商品种类、库存数量进行排序。 (2) 详细内容: 1 展示所有商品:列出仓库中所有商品的详细信息,包括商品编号、名称、商品种类、 库存 数量、供应商等。 2 根据库存数量排序:可以根据库存数量进行升序或降序排序,方便快速了解库存最多 的商 品和库存最少的商品。 3 根据商品种类排序:考虑商品种类,先对商品种类进行排序同类放在一起,然后对同 一类 别的商品再进行库存数量的排序(也要选择升序或者降序),方便快速了解某 一类别下库 存最多的商品和库存最少的商品。 4 生成盘点报告:生成基于“根据商品种类排序”盘点操作的所有商品库存信息的盘点报 告, 以 txt 文本格式存储。 8. 模糊查询的完善(备选功能) (1) 功能描述 :用户除了可依商品名称进行模糊查询外,还能选择更复杂的模糊查询模式,从 多维度查找商品,提高库存查询灵活性。 (2) 详细内容 : 1 用户输入商品名称关键词,可输入多个关键词,如 “乐” 和 “饮”,用逗号等分隔符隔开。 2 系统提供两种模糊查询模式供用户选择,全包含模式和任意包含模式 : 3 全包含模式 :查询商品名称同时包含所有输入关键词的商品,如输入 “乐”“饮”,只返 回名称同时含 “乐” 和 “饮” 的商品。 4 任意包含模式 :查询商品名称包含任一输入关键词的商品,如输入 “乐”“饮”,包含 “乐” 或 “饮” 中任意一个的商品都会被查询出来。 5 用户还可指定查询结果的排序方式(按库存数量升序 / 降序,按商品名称字母序等), 以及查询结果的数量上限(例如只看前 10 个匹配结果)。 6 系统根据上述条件并查询返回结果,展示信息与精确查询相同,并在查询结果开头显 示本次查询所用条件、模式等信息。若无匹配商品,提示 “未找到符合 [查询条件等描 述] 的商品”。数据结构设计: 1. 商品类别信息: (1) 字段:商品类别 ID(唯一标识)、商品类别名称 (2) 数据结构:字典列表 category _info= [ {"id": 1, "categoryName": "饮料类"}, ... ] 2. 供应商信息: (1) 字段:供应商 ID(唯一标识)、供应商名称 (2) 数据结构:字典列表 supplier_info = [ {"id": 1, "supplierName": "成都创新食品生产厂"}, ... ] 3. 用户信息 (1) 字段:用户 ID(唯一标识)、用户名、密码(加密存储) (2) 数据结构:字典列表,例如: user_info = [ {"id": 1, "username": "Tom", "password": "sads-=asd=iopalopas5"}, {"id": 2, "username": "Sam", "password": "saszxcrrsd6lzxc19qas5"}, ... ]4. 商品信息 (1) 字段:商品编号(唯一标识)、名称、商品类别 id、库存数量、供应商 id (2) 数据结构:字典列表,例如: product_info = [ { "id": 1, "productName": "可口可乐", "categoryId": 1, "quantity": 100, "supplierId": 1, }, ... ] 5. 入库记录 (1) 字段:入库单号(唯一标识)、商品编号、入库数量、进货日期、供应商、入库操作时间 (2) 数据结构:字典列表,例如: inbound_record = [ { "inbound_id": 1, "product_id": 1, "quantity": 50, "inbound_date": "2025-06-05", "supplierId": 1, "operation_time": "2025-06-05 10:00:00" }, ... ]6. 出库记录 (1) 字段:出库单号(唯一标识)、商品编号、出库数量、出库备注、出库操作时间 (2) 数据结构:字典列表,例如: outbound_record = [ { "outbound_id": 1, "product_id": 1, "quantity": 30, "outbound_ps": "小明购买了 30 瓶可乐", "operation_time": "2025-06-05 14:30:00" }, ...]评分标准 1. 功能完整性(30 分) 评估所有功能模块是否严格实现参考文本的要,包括核心功能和备选功能。每个功能根据 实现程度和细节完整性打分。 (1) 登录功能(5 分): 1 用户登录(1 分):输入用户名/密码,校验失败提示错误(如“用户名或密码错误”)。 2 用户注册(2 分):允许新用户注册,校验密码一致后加密存储到文件,并跳转登录 页(加盐加密必须实现)。 3 持久化存储(2 分):用户信息本地存储在 user_info.txt 文件(文本格式),密码加 密处理。 (2) 加解密功能(5 分): 1 凯撒加密/解密(2 分):正确实现字母移动(例如 A→D),处理数字/符号不变或偏 移。 2 加盐加密(3 分):使用 random 包生成 16 位随机盐,拼接后二次加密;解密流程能 剔除盐值还原原始密码。 (3) 库存查询功能(5 分): 1 精确查询(1 分):通过商品编号字段精确查询。 2 模糊查询(2 分):支持多关键词查询(逗号分隔),实现全包含/任意包含模式(备 选功能必须包含)。 3 库存范围查询(1 分):查询库存数量在指定范围内的商品。 4 显示信息(1 分):结果包括商品编号、名称、类别、库存数量、供应商(需从相关 数据结构中获取)。 (4) 入库操作(5 分): 1 输入与校验(2 分):输入商品编号、进货数量、供应商信息;校验商品编号唯一性 (错误提示),创建新商品时参数合法校验(如名称非空)。 2 更新与记录(2 分):更新库存数量,记录入库日期和操作时间(格式如 2025-6-5 14:11:23)。 3 入库单生成(1 分):自动生成入库单,并以 inbound_record.txt 文件持久化存储。 (5) 出库操作(5 分): 1 输入与校验(2 分):输入商品编号、出库数量、备注;校验库存充足性(不足时提 示“库存不足”)。 2 更新与记录(2 分):更新库存,记录出库时间和备注(格式一致)。 3 出库单生成(1 分):自动生成出库单,以 outbound_record.txt 文件持久化存储。(6) 手动信息更新(3 分): 1 编辑功能(2 分):允许添加/修改供货商、商品种类、商品基本信息(包括库存数 量)。 2 参数校验(1 分):检查输入合法性(如编号存在性、价格/数量正数)。 (7) 库存盘点(2 分): 1 展示与排序(1 分):展示所有商品详情,支持按库存数量或商品种类排序(同类内 再排序)。 2 报告生成(1 分):生成盘点报告到 inventory_audit_report.txt 文件。 2. 代码质量(25 分) 评估代码的结构、可读性、可维护性和效率。基于模块化、文档化、错误处理等方面打分。 (1) 模块化设计(10 分): 1 函数分离(6 分):每个功能模块(如登录、查询、加解密)封装成独立函数,避免 重复代码。 2 数据结构处理(4 分):使用类或函数加载/保存数据文件(如 load_data()和 save_data())。 (2) 可读性和注释(5 分): 1 代码注释(3 分):关键逻辑有中文注释(例如凯撒加密算法解释)。 2 命名规范(2 分):变量和函数名语义化(如 caesar_encrypt、inventory_inbound)。 (3) 错误处理和鲁棒性(5 分): 1 输入验证(3 分):处理非法输入(如非数字编号、负数数量),提供友好提示。 2 异常处理(2 分):文件操作错误捕获(例如文件不存在时初始化)。 (4) 效率优化(5 分): 1 算法实现(3 分):查询功能效率高(如模糊查询使用列表推导而非嵌套循环)。 2 数据访问(2 分):数据结构加载只读时用缓存(例如用字典映射 ID)。3. 用户交互与菜单设计(20 分) 评估控制台程序的实际交互体验,包括菜单导航、输入输出设计和可用性。 (1) 菜单层次(5 分): 1 主菜单设计(3 分):提供清晰选项(如 1-登录、2-查询等),选项覆盖所有功能。 2 子菜单集成(2 分):次级菜单无缝集成(例如库存查询下选择模糊查询模式)。 (2) 输入输出友好性(5 分): 1 提示信息(3 分):输入时提供格式说明(例如“请输入用户名”),输出格式化(如 查询结果用表格)。 2 错误反馈(2 分):错误提示明确(如“库存不足”、“输入无效”),引导重新输入。 (3) 用户体验细节(5 分): 1 操作流(3 分):注册后自动跳转登录;入库/出库后显示单据。 2 一致性(2 分):所有时间格式统一(如“2025-6-5 14:11:23”)。 (4) 持久化存储交互(5 分): 1 文件更新(3 分):数据变更后实时写入文件。 2 报告可访问(2 分):生成报告后提示文件路径(如“盘点报告已保存在 inventory_audit_report.txt ”)。 4. 数据结构遵守度(15 分) 评估是否严格遵守参考文本中的数据结构定义,字段、格式和存储要(1) 数据结构完整性(5 分): 1 字段匹配(3 分):所有字典字段存在(如商品信息包括 id、productName 等)。 2 文件存储格式(2 分):数据以文本文件存储(JSON 或类似),文件名正确(如 product_info.txt )。 (2) 数据关联性(5 分): 1 ID 一致性(3 分):ID 关联正确(例如查询供应商时显示供应商名称而非 ID)。 2 列表结构(2 分):数据保存为字典列表(如 product_info = [{"id":1, ...}, ...])。 (3) 数据验证(5 分): 1 参数校验(3 分):添加商品时检查类别/供应商 ID 存在(如手动更新功能)。 2 数据持久化(2 分):启动时自动初始化文件(如 init_data()函数)。5. 报告(20 分) 课程报告撰写格式规范,内容完整,课程设计报告的具体要模板。覆盖所有指定部分: 报告必须完整包含参考文本中的六大模块,每个模块需详细阐述。 (1) 项目背景与意义:结合实际应用场景,分析仓储管理的需痛点。 (2)分析:基于课程设计题目,细化用户身份认证模块(如登录/注册功能需)。 (3) 系统设计:描述系统架构、功能模块(如登录/注册模块的流程和数据结构)。 (4) 系统实现关键技术:说明开发环境(Python 版本、库如 random 和 datetime)、核心功能 实现(如用户信息管理流程)。 (5) 系统测试:展示操作流程、模块交互截图,确保可重现。 (6) 总结与展望:反思成果、不足及未来优化方向。 总权重 20 分:拆分为两个主要维度。 (1) 格式规范(占 5 分): 1 布局正确(2 分):如页边距、标题层级无误。 2 视觉元素合规(2 分):图表编号清晰、代码块格式统一。 3 文档元素完整(1 分):封面、目录等齐全。 (2) 内容完整(占 15 分): 1 覆盖所有模块(10 分):每个部分(背景、需、设计等)均有详述。 2 逻辑清晰详实(5 分):各部分衔接自然,内容深度足够(如需分析中登录功能需 的细节)。
06-16
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值