news 2026/4/16 16:14:56

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/4/16 9:09:03

艾体宝方案 | 身份与访问管理(IAM)如何强化企业合规性

简介本文基于 IBM《2024 年数据泄露成本报告》揭示的全球数据安全现状&#xff0c;系统阐述了身份与访问管理&#xff08;IAM&#xff09;在企业合规管理中的核心价值。文章首先剖析了合规与 IAM 的紧密关联&#xff0c;指出 IAM 是实现高水准责任追溯、应对动态合规需求的关键…

作者头像 李华
网站建设 2026/4/16 9:07:46

实战蓝图:从诊断到闭环的GEO五步法操作体系

理解了GEO的“为什么”&#xff0c;下一步是关键且具体的“怎么做”。本文将系统拆解一套经过验证的、可落地的GEO实战框架&#xff0c;即“诊断、策略、生成、投放、迭代”五步闭环体系。 一、第一步&#xff1a;全景诊断 —— 摸清AI眼中的品牌现状 盲目优化等于资源浪费。…

作者头像 李华
网站建设 2026/4/16 11:07:33

mise 安装及使用指南

介绍mise&#xff08;发音同 “mice”&#xff09;是一款用 Rust 编写的高性能多运行时版本管理器&#xff0c;它能够帮助开发者在单个工具中统一管理多种编程语言和工具的版本。核心价值多语言统一管理&#xff1a;支持 Node.js、Python、Ruby、Go、Java、Rust 等多种语言和工…

作者头像 李华
网站建设 2026/4/16 10:41:44

好写作AI:当AI能写论文了,老师您到底在教什么、考什么?

当学生的论文查重率1%&#xff0c;文笔优美、格式规范&#xff0c;但被问到“你的核心论点是怎么想出来的”时却支支吾吾——老师&#xff0c;您是否也开始怀疑&#xff0c;自己批改的究竟是一份作业&#xff0c;还是AI的“产品使用报告”&#xff1f;尊敬的老师们&#xff0c;…

作者头像 李华
网站建设 2026/4/16 9:06:13

AI数字人小程序核心玩法拆解与技术运营分析

在生成式AI技术规模化落地的浪潮中&#xff0c;AI数字人小程序凭借“低门槛创作高场景适配”的核心优势&#xff0c;快速渗透电商、科普、客服等多领域&#xff0c;成为技术普惠与商业变现的核心载体。其玩法设计紧扣“技术降本运营提效”&#xff0c;融合生成式交互、场景定制…

作者头像 李华