news 2026/2/3 12:57:52

UVa 148 Anagram Checker

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
UVa 148 Anagram Checker

题目分析

本题要求编写一个程序,从给定的字典中找出所有能够由指定短语中的字母重组而成的单词组合。输入分为两部分:首先是字典部分(每行一个单词,按字母顺序排序),然后是需要检查的短语列表(每行一个短语)。两个部分均以单独一行的#结束。

字典最多包含2000 20002000个单词,每个单词或短语的长度不超过20 2020个字符。所有输入均为大写字母,且不限于英语单词。

输出要求:对于每个短语,输出所有可能的字典单词组合(按字母顺序排列),这些组合中的单词全部来自字典,且恰好用尽短语中的所有字母(忽略空格),且不能与原短语完全相同(即不能只是原单词的顺序不同)。如果没有找到任何组合,则不输出任何内容(包括空行)。

解题思路

这个问题本质上是一个搜索与剪枝问题。由于字典和短语的规模不大(2000 20002000个单词,每个短语最多20 2020个字母),我们可以使用回溯法(backtracking \texttt{backtracking}backtracking结合字母计数法来高效求解。

核心思路

  1. 字母计数表示
    每个单词和短语都可以用一个长度为26 2626的数组表示,记录每个字母出现的次数。这种表示方式便于快速判断单词是否可由给定字母组成,以及是否已用尽所有字母。

  2. 预处理字典
    读取字典时,为每个单词存储其原始字符串和对应的字母计数数组。

  3. 处理每个短语

    • 计算短语的字母计数(忽略空格)作为目标数组goalCount
    • 将原短语按空格分割成单词列表single,用于后续排除与原短语完全相同的组合。
    • 使用回溯法从字典中选取单词组合,使得组合的字母计数等于goalCount
    • 在回溯过程中,利用字母计数进行剪枝:如果当前选取的单词会导致某个字母的数量超过目标值,则跳过该单词。
  4. 回溯搜索

    • 状态:当前已选取的单词列表、当前字母计数数组currentCount
    • 终止条件:已选取单词的总长度等于短语字母总数(即所有字母已用尽)。
    • 剪枝条件:
      • 单词长度超过剩余可用字母数。
      • 单词的某个字母数量加上当前计数超过目标值。
    • 去重:确保输出组合的单词按字母顺序排列,并排除与原短语单词列表完全相同(只是顺序不同)的组合。
  5. 输出格式
    输出时,先输出原短语,后跟=,再依次输出按字母顺序排序的单词组合。

算法复杂度分析

  • 字典大小:M ≤ 2000 M \leq 2000M2000
  • 短语字母数:L ≤ 20 L \leq 20L20
  • 回溯的深度取决于单词长度,但剪枝能显著减少搜索空间。
  • 最坏情况下搜索空间是指数级的,但实际由于字母限制和剪枝,运行效率较高。

实现细节

  • 使用结构体item存储单词及其字母计数。
  • 使用全局数组used标记字典单词是否已被使用。
  • 回溯函数backtrack从起始索引开始,避免重复组合。
  • 输出前对单词组合按字母顺序排序,并比较与原短语单词列表是否相同。

代码实现

// Anagram Checker// UVa ID: 148// Verdict: Accepted// Submission Date: 2016-01-22// UVa Run Time: 0.059s//// 版权所有(C)2016,邱秋。metaphysis # yeah dot net#include<bits/stdc++.h>usingnamespacestd;structitem{string word;intcount[26];};item words[2001];intgoalCount[26],currentCount[26];vector<string>single;boolused[2001];intwordGet[2001],indexGet,total;string targetLine;voidisGood(){boolgood=true;for(inti=0;i<26;i++)if(currentCount[i]!=goalCount[i]){good=false;break;}if(!good)return;if(indexGet==single.size()){vector<string>t1(single),t2;for(inti=0;i<indexGet;i++)t2.push_back(words[wordGet[i]].word);sort(t1.begin(),t1.end());sort(t2.begin(),t2.end());boolgood=false;for(inti=0;i<t1.size();i++)if(t1[i]!=t2[i]){good=true;break;}if(!good)return;}cout<<targetLine<<" =";for(inti=0;i<indexGet;i++)cout<<" "<<words[wordGet[i]].word;cout<<endl;}voidbacktrack(intstart,intlength,inttarget){if(length==target){isGood();return;}for(inti=start;i<total;i++){if(used[i])continue;if((length+words[i].word.length())>target)continue;boolgood=true;for(intj=0;j<26;j++)if((words[i].count[j]+currentCount[j])>goalCount[j]){good=false;break;}if(!good)continue;wordGet[indexGet++]=i;used[i]=true;for(intj=0;j<26;j++)currentCount[j]+=words[i].count[j];backtrack(i+1,length+words[i].word.length(),target);for(intj=0;j<26;j++)currentCount[j]-=words[i].count[j];used[i]=false;indexGet--;}}intmain(){string line;total=0;while(getline(cin,line),line!="#"){item aItem;aItem.word=line;memset(aItem.count,0,sizeof(aItem.count));for(inti=0;i<line.length();i++)aItem.count[line[i]-'A']++;words[total++]=aItem;}while(getline(cin,line),line!="#"){intalphaCount=0;targetLine.assign(line);memset(goalCount,0,sizeof(goalCount));for(inti=0;i<line.length();i++)if(isalpha(line[i])){goalCount[line[i]-'A']++;alphaCount++;}single.clear();istringstreamiss(line);string word;while(iss>>word)single.push_back(word);memset(currentCount,0,sizeof(currentCount));memset(used,0,sizeof(used));indexGet=0;backtrack(0,0,alphaCount);}return0;}

总结

本题通过字母计数法回溯剪枝高效解决了多单词字母重组问题。关键在于:

  • 使用计数数组代替字符串直接比较,提升效率。
  • 在回溯过程中尽早剪枝,减少无效搜索。
  • 输出时注意排序和去重,符合题目要求。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/2 7:54:42

10410_基于Springboot的文化旅游宣传网站

1、项目包含项目源码、项目文档、数据库脚本、软件工具等资料&#xff1b;带你从零开始部署运行本套系统。2、项目介绍以甘南藏族自治州为例&#xff0c;其丰富的自然遗产与人文景观构成了独特的旅游生态体系&#xff0c;年接待游客量突破千万人次的背景下&#xff0c;旅游管理…

作者头像 李华
网站建设 2026/2/1 10:22:17

计算机毕业设计springboot高校师范生实习管理小程序 基于SpringBoot的高校师范生教育实习过程管理与协同平台 SpringBoot框架下的师范生教学实践移动化管理信息系统

计算机毕业设计springboot高校师范生实习管理小程序 &#xff08;配套有源码 程序 mysql数据库 论文&#xff09; 本套源码可以在文本联xi,先看具体系统功能演示视频领取&#xff0c;可分享源码参考。 在教育数字化转型持续深化的背景下&#xff0c;师范生教育实习作为连接理论…

作者头像 李华
网站建设 2026/2/3 13:10:14

期货交易API入门:Python接口使用指南

免责声明&#xff1a;本文为个人学习笔记&#xff0c;仅供技术交流&#xff0c;不构成任何投资建议。 刚开始接触Python期货量化&#xff0c;可能会对"怎么用代码获取行情"、"怎么用代码下单"这些基础问题感到困惑。本文从零开始&#xff0c;记录一下期货交…

作者头像 李华
网站建设 2026/2/2 22:44:05

一块板子的良率,从安装开始:电子厂生产线设备安装的关键真相

一、什么是电子厂生产线设备安装&#xff1f; 电子厂生产线设备安装&#xff0c;是指在电子制造企业的新建、扩建或技术改造过程中&#xff0c;围绕SMT贴片、插件、组装、测试、包装等核心工艺&#xff0c;对生产设备进行就位、安装、找平、连接、联调和试运行的系统性工程。 …

作者头像 李华