蓝桥杯 契合匹配

原题目链接

题目描述

小蓝有很多齿轮,每个齿轮的凸起和凹陷分别用一个字符表示,一个字符串表示一个齿轮。

如果两个齿轮的对应位分别是同一个字母的大小写,我们称这两个齿轮是契合的。

例如:

  • "AbCDeFgh" 和 "aBcdEfGH" 是契合的
  • "abc" 和 "aBC" 不是契合的

这天,小蓝的弟弟小桥从抽屉里拿来了两个齿轮,小蓝想知道,这两个齿轮是不是契合的。

特别需要注意的是,齿轮是环形的,所以是可以旋转的(顺时针和逆时针均可)。如果是契合的,小蓝还想让你告诉他,最少将第一个齿轮旋转多少位,两个齿轮可以完全契合在一起。

例如:

  • "AbbCd" 和 "BcDaB" ,将第一个齿轮逆时针旋转两位后变成 "bCdAb",两个齿轮就完全契合在一起了。

输入格式:

  • 第一行输入一个正整数 n,表示两个齿轮的长度。
  • 第二行输入一个长度为 n 的字符串 S,表示第一个齿轮。
  • 第三行输入一个长度为 n 的字符串 T,表示第二个齿轮。

输出格式:

  • 第一行输出一个字符串:"Yes" 或者 "No",表示两个齿轮是否契合。
  • 如果可以契合,第二行输出一个整数,表示需要旋转的位数。
  • 如果不可以契合,不用多余输出。

样例输入:

in 复制代码
5
AbbCd
BcDaB

样例输出:

out 复制代码
Yes
2

评测数据范围:

  • 1 ≤ n ≤ 10^6
  • 保证字符串只包含大小写字母。

c++代码(超时版)

cpp 复制代码
#include<bits/stdc++.h>

using namespace std;

int n;
string S, T;

int main() {
    cin >> n >> S >> T;
    for (int i = 0; i < n; i++) {
        if (isupper(T[i])) T[i] = tolower(T[i]);
        else T[i] = toupper(T[i]);
    }
    S += S;
    int k = S.find(T);
    k = min(k, n - k);
    if (k == -1) cout << "No" << endl;
    else cout << "Yes" << endl << k << endl;
    return 0;
}//by wqs

c++代码(KMP算法优化)

cpp 复制代码
#include<bits/stdc++.h>

using namespace std;

int n;
string S, T;
int Next[1000009];

void getNext(string p) {
	Next[0] = 0, Next[1] = 0;
	for (int i = 1; i < p.size(); i++) {
		int j = Next[i];
		while (j && p[i] != p[j]) j = Next[j];
		if (p[i] == p[j]) Next[i + 1] = j + 1;
		else Next[i + 1] = 0;
	}
}

int kmp(string s, string p) {
	getNext(p);
	int j = 0;
	for (int i = 0; i < s.size(); i++) {
		while (j && s[i] != p[j]) j = Next[j];
		if (s[i] == p[j]) j++;
		if (j == p.size()) return i + 1 - p.size();
	}
	return -1;
}

int main() {
	cin >> n >> S >> T;
	for (int i = 0; i < n; i++) {
		if (isupper(T[i])) T[i] = tolower(T[i]);
		else T[i] = toupper(T[i]);
	}
	S += S;
	int k = kmp(S, T);
	k = min(k, n - k);
	if (k == -1) cout << "No" << endl;
	else cout << "Yes" << endl << k << endl;
	return 0;
}//by wqs

我们首先不考虑旋转 ,判断字符串 a 和字符串 b 是否契合,等价于:a 中的小写字母与 b 中的大写字母相对应,a 中的大写字母与 b 中的小写字母相对应。例如,aBcdEfAbCDeF 是契合的。

为了简化判断过程,我们可以将字符串 b 中的大写字母全部转换为小写字母,小写字母转换为大写字母。假设字符串 bAbCDeF,经过转换后变为 aBcdEf。此时,问题就转化为判断字符串 a 和转换后的字符串 b 是否相等。

通过这种方法,我们可以轻松判断两个字符串是否相契合。

当然这是不考虑旋转的情况,要考虑旋转,我们就要用到破环成链思想。

如果一个字符串 S (abcdef )扩展成两倍 S′ ( abcdefabcdef ),那么从 S′ 的第二个字符开始 6 个字符组成的子串( bcdefa ),实际上就是 S 逆时针旋转 1 位的字符串,同时也是顺时针旋转 5 位的情况。

那么这个问题就转换为了,T转换过后的字符串是否是两倍S的子串。

相关推荐
Wang's Blog3 分钟前
AI Agent白手起家30: 动态示例选择器之根据长度选择 Few Shot 示例
算法
oyguyteggytrrwwwrt2 小时前
自制交叉线路识别算法
算法
手写码匠2 小时前
华为云Flexus+DeepSeek征文|Dify 多智能体协同编排实战:R1 规划 + V3 执行,构建企业 Agent 团队
人工智能·深度学习·算法·aigc
晓天衡宇•评测社区3 小时前
FSR-Bench 前沿科学推理榜单发布:GPT-5.5 居首,“会推理”未必“能答对”
算法
程序喵大人4 小时前
【C++进阶】STL算法与函数对象 - 02 sort为什么需要随机访问迭代器
开发语言·c++·算法
hanlin034 小时前
动态规划专练:力扣第121、122题
笔记·算法·leetcode
To_OC4 小时前
LC 74 搜索二维矩阵:换皮的二分查找,我居然一开始没看出来
javascript·算法·leetcode
文心快码BaiduComate4 小时前
文心快码荣获“中国优秀软件产品”,实力再获国家级认可
算法·代码规范
玖玥拾4 小时前
LeetCode 189 轮转数组
算法·leetcode
ZhangShao06074 小时前
题解:CF2249B
c++·算法