P9013 [USACO23JAN] Find and Replace S
前言
这是考试的时候放的一道题,考的时候没做出来。
调了一个晚上,心态爆炸,故作此篇。顺便,鸣谢泥土笨笨大佬的题解,给我的代码提供了强有力的对拍参照。
正题
首先看到题目,虽然字符串长度不超过 \(10^5\),但是还是嫌多;再一看,至多只有52个字符。
那么从这个数据范围入手,思考可以按照变换前后的字符串给所有字符建一张图,其中的每一条有向边 \(a \rightarrow b\) 表示变换前的字符 \(a\) 变成了字符 \(b\)。接下来思考这个图可能有哪几种形式:
首先讨论 1:显然无解!一个字符不可能同时分裂成两种不同的字符。所以,我们得到了第一种无解的判定。
其次讨论形成一条链(2):显然的,假设这条链有 \(n\) 条边,可以在 \(n\) 次转化后完成。
然后是一个环(3):这就无法用 \(n\) 次完成了,必须先将某个点换成另一种字符,转化成一条有 \(n+1\) 个节点的链来做,所以要 \(n+1\) 次完成。
最后是生出尾巴的环(4):刹一看,好像要 \(n+1\) 次完成;其实不用。把入度为 \(2\) 的点叫做点 \(a\),尾巴上指向 \(a\) 的点是 \(b\),环上指向 \(a\) 的是 \(c\),可以现将点 \(c\) 换成字符 \(a\),转换成一条 \(n\) 的链,最后 \(c\) 和 \(a\) 一起变成 \(b\)。所以也是只用 \(n\) 次。
当然,实际处理中这三种总是会一起出现(2,3,4),那么只要意义处理就行。
除了上面提到的第一种无解,还有一种情况就是转换后的字符串包含了所有的字符(\(52\) 个),并且和转换前的字符串不同。这时候,若画出图来应该是一个 \(52\) 个点的环,由于没有一个点可以变成另一个不同于这 \(52\) 个点的字符,所以也是无解。
那么代码就好实现了。不过这里有几点需要注意:
从入度小的点开始遍历图,而不是按照字母顺序。
判断一个字符是否要同事变成两个字符时,别忘了把它自己算上。
接下来是代码时间(写法丑陋,仅作参考):
#include <bits/stdc++.h>
using namespace std;
int nxt[55],id[128],ans,T;
bool vis[55],has[55],noind[55];
char s1[100005],s2[100005];
void init() {
ans=0;
memset(nxt,0,sizeof(nxt));
memset(vis,false,sizeof(vis));
memset(has,false,sizeof(has));
memset(noind,true,sizeof(noind));
memset(s1,0,sizeof(s1));
memset(s2,0,sizeof(s2));
return ;
}
void addans(int p) {
if(vis[p]) return ;
int v=p,type=0;
vis[p]=true;
while(nxt[v]) {
type++,v=nxt[v];
if(v==p) {
ans+=type+1;
return ;
}
if(vis[v]) {
ans+=type;
return ;
}
vis[v]=true;
}
ans+=type;
return ;
}
int main() {
scanf("%d",&T);
for(int i=0;i<26;i++) id[i+'A']=i+1,id[i+'a']=i+27;
// for(int i='A';i<='Z';i++) cout<<char(i)<<":"<<id[i]<<endl;
// for(int i='a';i<='z';i++) cout<<char(i)<<":"<<id[i]<<endl;
while(T--) {
init();
scanf("%s%s",s1+1,s2+1);
int len=strlen(s1+1);
bool no_ans=false,same=true;
set<char> chset;
for(int i=1;i<=len;i++) {
int id1=id[s1[i]],id2=id[s2[i]];
if(has[id1]&&(id2!=nxt[id1])) {
no_ans=true;
break;
}
else {
has[id1]=true,nxt[id1]=id2;
if(id1!=id2) noind[id2]=false,same=false;;
}
chset.insert(s2[i]);
}
if(same) {
printf("0\n");
continue;
}
for(int i=1;i<=52;i++)
if(nxt[i]==i) nxt[i]=0;
for(int i=1;i<=52;i++)
if(noind[i]) addans(i);
for(int i=1;i<=52;i++)
if(has[i]) addans(i);
if(no_ans) printf("-1\n");
else if(chset.size()==52) printf("-1\n");
else printf("%d\n",ans);
}
return 0;
}
完结撒花!!!
P9013 [USACO23JAN] Find and Replace S的更多相关文章
- <JavaScript语言精粹>--<读书笔记三>之replace()与正则
今天有人问我repalce(),他那个题目很有意思.我也不会做,于是我就去查,结果发现就是最基础的知识的延伸. 所以啊最基础的知识才是很重要的,千万不能忽略,抓起JS就写代码完全不知到所以然,只知道写 ...
- StackOverFlow排错翻译 - Python字符串替换: How do I replace everything between two strings without replacing the strings?
StackOverFlow排错翻译 - Python字符串替换: How do I replace everything between two strings without replacing t ...
- js的replace函数入参为function时的疑问
近期在写js导出excel文件时运用到replace方法,此处详细的记录下它各个参数所代表的的意义. 定义和用法 replace() 方法用于在字符串中用一些字符替换另一些字符,或替换一个与正则表达式 ...
- ORACLE 利用 REPLACE函数替换字段字符串
REPLACE(string,s1,s2) string 希望被替换的字符或变量 s1 被替换的字符串 s2 要替换的字符串 SQL> select replace(he love you,he ...
- js 页面刷新location.reload和location.replace的区别小结
reload 方法,该方法强迫浏览器刷新当前页面. 语法: location.reload([bForceGet]) 参数: bForceGet, 可选参数, 默认为 false,从客户端缓存里取当前 ...
- replace和translate的用法
select replace ('111222333444','222','888') from dual;with tmp as(select 'aabb/123\:cde工人' s from du ...
- JavaScript replace() 方法
参考:http://www.w3school.com.cn/jsref/jsref_replace.asp 需要有一点注意的是:可以是函数的形式做为返回值,如下: "test{0}" ...
- replace实现正则过滤替换非法字符
html+js结构如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http: ...
- Replace 删除、替换函数精解示例
'************************************************************************* '**模 块 名:Replace函数精解示例 '* ...
- angularjs 指令详解 - template, restrict, replace
通过指令机制,angularjs 提供了一个强大的扩展系统,我们可以通过自定义指令来扩展自己的指令系统. 怎样定义自己的指令呢? 我们通过 Bootstrap UI来学习吧.这个项目使用 angula ...
随机推荐
- 导入别人的android studio项目
在导入别人的android studio项目(假设为项目A)时,会遇到gradle不一致的情况,以下简短介绍解决方法: 1. 打开要导入的项目的目录,删除下图红框中的文件. 2. 找到自己以前在自己的 ...
- rust程序静态编译的两种方法总结
1. 概述 经过我的探索,总结了两种rust程序静态编译的方法,理论上两种方法都适用于windows.mac os和linux(mac os未验证),实测方法一性能比方法二好,现总结如下,希望能够帮到 ...
- 【Uber 面试真题】SQL :每个星期连续5星评价最多的司机
大家好,我是"蒋点数分",多年以来一直从事数据分析工作.从今天开始,与大家持续分享关于数据分析的学习内容. 本文是第一篇,也是[SQL 周周练]系列的第一篇.该系列是挑选或自编具有 ...
- C#开发的Panel滚动分页控件 - 开源研究系列文章
前些时候因为想拥有一个自己的软件快捷打开软件,于是参考Windows 11的开始菜单,进行了编写这个应用软件,里面有一个功能就是对显示的Panel里的应用对象的分页功能,于是就想写一个对Panel的自 ...
- MCP 实践系列:看热点、蹭热点,创作与摸鱼两手抓!
连续工作累死人,身心疲惫时,总得有那么一点时间给自己松口气.每当这个时候,我总喜欢偷偷摸摸地看看新闻,整理一下逐渐疯狂的思维.毕竟,谁说程序员就只能埋头写代码?谁规定了只能死磕在堆积如山的bug中? ...
- HashMap put方法源码解析|Java 17
Put函数源码解析HashMap的put方法执行过程可以通过下图来理解(摘自某大厂的博客,推荐从参考文献的链接去查看原文),自己有兴趣可以去对比源码更清楚地研究学习. 欲了解更多HashMap ...
- HNU FPGA课设项目上手指南
1.介绍 本文章旨在帮助HNU的同学更优雅的完成数电的FPGA课设(使用DE2-115),文章将涉及完成FPGA项目需要掌握的知识,资源分享以及一些关于完成项目的经验指导.大家快快搬好小板凳,准备发车 ...
- DeepSeek + Mermaid:零代码玩转专业流程图
一.工具组合超能力解析 黄金组合优势: 语言到图表的直接转换 - 用中文描述即可生成专业图表 动态修正能力 - 实时调整描述立即更新图表 企业级复杂度支持 - 轻松处理多层级流程 零安装成本 - 纯W ...
- ChatMoney让你体验古诗词的快乐
本文由 ChatMoney团队出品 介绍说明 在中华传统文化的璀璨星空里,诗词宛如熠熠生辉的明珠,而飞花令则是其中一颗独特而耀眼的星辰.如今,我们自豪地为您推出专为孩子精心打造的飞花令机器人,为孩子们 ...
- CJ20N 增强客户字段 引用别人公众号文章
引用:PS CJ20N 项目定义属性字段增强 (qq.com) 达成效果: 一.CJ20N添加字段 二.用户出口CNEX0006 CMOD分配CNEX0006 出口EXIT_SAPLCJWB_002 ...