蓝桥杯 契合匹配

原题目链接

题目描述

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

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

例如:

  • "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的子串。

相关推荐
写代码写到手抽筋1 小时前
5G上行DCI字段判定:端口 流数 PMI选择详解
java·算法·5g
xieliyu.1 小时前
Java算法精讲:双指针(二)
java·开发语言·算法
wayz112 小时前
Momentum:PSL(心理线指标)技术指标详解
算法·金融·数据分析·量化交易·特征工程
8Qi83 小时前
LeetCode 213:打家劫舍 II(House Robber II)—— 题解 ✅
算法·leetcode·职场和发展·动态规划
三品吉他手会点灯3 小时前
C语言学习笔记 - 44.运算符和表达式 - 运算符2 - 除法与取余运算符
c语言·开发语言·笔记·算法
乐迪信息3 小时前
乐迪信息:AI算法盒子实时识别船舶烟雾与火焰异常
大数据·人工智能·算法·安全·目标跟踪
J-Tony113 小时前
【JVM】根可达算法
jvm·算法
艾iYYY3 小时前
string 类的模拟实现
android·服务器·c语言·c++·算法
Lsk_Smion4 小时前
力扣实训 _ [75].颜色分类 _ 杨辉三角
数据结构·算法·leetcode