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

UVa 628 Password

题目描述

给定一个由若干单词组成的字典和若干规则,每个规则由字符#0组成,其中#表示从字典中选取一个单词,0表示选取一个数字(000999)。要求生成所有可能的密码,即用字典中的单词依次替换规则中的#,用数字替换规则中的0,得到的所有字符串。输出时按规则顺序,同一规则下按字典顺序(单词按字典输入顺序,数字按升序)。输入可能包含多组数据(每组由字典和若干规则组成)。

输入格式

第一行为一个整数nnn0<n≤1000 < n \le 1000<n100),表示字典中的单词数量。接下来nnn行,每行一个单词(长度111255255255,由字母和数字组成)。随后一行是一个整数mmmm<1000m < 1000m<1000),表示规则数量。接下来mmm行,每行一个规则(长度不超过255255255),由字符#0组成,其中至少含有一个0#可有可无。输入包含多组这样的数据,直到文件结束。

输出格式

对于每组数据,首先输出一行--(两个连字符)。然后对于每条规则,按顺序输出所有匹配的密码(即按照规则中#0的位置,用字典中的单词和数字替换后产生的全部字符串)。同一规则下,数字部分按升序(000999)生成,单词部分按字典输入顺序依次替换,形成笛卡尔积。字典序由规则中#0的位置决定(即替换顺序固定为从左到右)。

样例

输入

2 root 2super 1 #0 1 admin 1 #0#

输出

-- root0 root1 root2 2super0 2super1 2super2 2super3 2super4 2super5 2super6 2super7 2super8 2super9 -- admin0admin admin1admin admin2admin admin3admin admin4admin admin5admin admin6admin admin7admin admin8admin admin9admin

题目分析

本题是典型的排列组合生成问题。规则中的每个#位置可以放置任意一个字典单词,每个0位置可以放置任意一个数字000999。最终密码由规则串中的符号顺序决定,只需依次替换即可。由于0出现次数最多777次,#出现次数不限(但规则长度有限),因此组合数量可能很大,但题目要求全部输出,只需递归枚举。

解题思路

  1. 读入字典单词,存入数组。
  2. 读入规则个数,对每条规则:
    • 将规则中的0替换为另一个字符(如$)以便在递归中区分数字和单词位置(代码中直接用rule[j] == '0'判断,但改为$是为了在回溯时统一处理)。
    • 使用深度优先搜索(DFS\texttt{DFS}DFS)遍历规则串的每个位置:
      • 若当前位置字符为#,则枚举所有字典单词(按输入顺序),将对应单词输出(或存储到临时数组),继续递归。
      • 若当前位置字符为$(即原0),则枚举数字000999,继续递归。
    • 当遍历完规则串所有位置时,将临时数组中的内容拼接成密码并输出。
  3. 每组数据开始时输出--,每条规则生成的密码连续输出,不同规则间无额外空行。

复杂度分析

  • 设字典大小为nnn,规则长度为LLL,其中#个数为aaa0个数为bbb,则密码总数为na×10bn^a \times 10^bna×10b。由于b≤7b \le 7b7aaa受规则长度限制(L≤255L \le 255L255),但n≤100n \le 100n100,在最坏情况下数量可能极大,但题目要求全部输出,因此必须接受。
  • 递归深度为LLL,每次递归枚举nnn101010种选择,时间复杂度正比于输出数量。

代码实现

// Passwords// UVa ID: 628// Verdict: Accepted// Submission Date: 2016-08-27// UVa Run Time: 0.000s//// 版权所有(C)2016,邱秋。metaphysis # yeah dot net#include<bits/stdc++.h>usingnamespacestd;intn,m,password[260];string dictionary[110];voidbacktrack(string rule,intdepth){if(depth==rule.length()){for(inti=0;i<rule.length();i++){if(password[i]>=0)cout<<dictionary[password[i]];elsecout<<(char)('0'+password[i]+10);}cout<<'\n';}else{if(rule[depth]=='#'){for(intj=0;j<n;j++){password[depth]=j;backtrack(rule,depth+1);}}else{for(intj=0;j<=9;j++){password[depth]=j-10;backtrack(rule,depth+1);}}}}intmain(){cin.tie(0);cout.tie(0);ios::sync_with_stdio(false);string rule;while(cin>>n){for(inti=0;i<n;i++)cin>>dictionary[i];cout<<"--\n";cin>>m;for(inti=1;i<=m;i++){cin>>rule;for(intj=0;j<rule.length();j++)if(rule[j]=='0')rule[j]='$';backtrack(rule,0);}}return0;}

总结

本题通过深度优先搜索枚举规则中每个符号的所有可能选择,生成所有密码。关键点在于:

  • 用数组password记录每个位置选择的索引(单词索引或负数表示数字)。
  • 数字位置用负值表示,输出时转换回字符。
  • 规则中0替换为$,便于在递归中区分。
  • 输出顺序由规则顺序和字典顺序自然决定,因为单词按输入顺序枚举,数字按升序枚举。

该解法直接暴力的生成所有组合,适合规则中0数量少的情况,若0数量较多(最多 7 个),输出量可能巨大,但题目要求如此。

http://www.gsyq.cn/news/1645716.html

相关文章:

  • GitHub资源列表自动化维护:链接监控与README生成实战
  • JMeter分布式性能测试实战:从架构原理到避坑指南
  • Cantian connector for MySQL部署最佳实践:CentOS平台完整配置指南
  • TOTP双因素认证时钟同步原理与终极解决方案
  • 从RAG到智能体:构建工程化Agentic RAG系统的完整指南
  • 如何快速上手MLCacheDirect?从安装到基本使用的完整指南
  • UVa 627 The Net
  • Fable 5代理编码的瓶颈转移 地图领土与四类未知的系统拆解
  • 复杂异形檐口铝板幕墙安装技术
  • 终极指南:深入理解 chaosArsenal - Linux系统可靠性测试的革命性工具
  • 鸿蒙5G-6G-7G全域通感超域升维理论百篇体系总纲
  • stortrace与ext4文件系统:深入分析DIO操作的延迟构成终极指南 [特殊字符]
  • TensorFlow 1.x 路径拼接引发 0xC0000005:3 种文件 I/O 访问冲突排查与修复
  • openEuler/QoS-Deployment-Test:10个步骤完成CPU QoS资源隔离验证测试
  • Xenomai实时应用开发实战:3种皮肤接口(Skins)使用对比
  • Taishan-oslab架构深度解析:Docker容器化部署与微服务设计终极指南 [特殊字符]
  • SoftBR信号处理机制:如何实现无侵入的分支采样
  • 空洞骑士Scarab模组管理器:如何轻松安装和管理游戏模组
  • Linux服务器安全加固:ClamAV命令行扫描实战与自动化配置指南
  • Hey安全最佳实践:确保命令行AI智能体的安全使用指南
  • openEuler/QoS-Deployment-Test:IO资源隔离测试的终极教程
  • 从0到1学习WasmEngine:开发者必备的WebAssembly函数引擎入门教程
  • Taishan-oslab GitLab集成指南:云端代码管理与协作最佳实践
  • OpenDesign miniprogram:openEuler社区一站式会议与活动管理小程序完整指南
  • 为什么选择WasmEngine?5大核心优势让你的WebAssembly函数执行效率提升300%
  • 解决跨镜断轨:视频孪生拓扑图谱推理技术详
  • 如何快速上手OpenEuler workflowkits:5分钟搭建你的第一个命令编排流程
  • 如何快速参与intel-iavf开源项目:面向新手的完整开发者指南
  • FalconFS架构深度解析:揭秘支持10,000+ NPU的分布式文件系统核心技术
  • UTBotJava性能优化技巧:如何配置设置文件提升测试生成速度