CSP202409B - 字符串变换

· Soln

题目描述

本题涉及的字符共有 6363 种,包括大小写英文字母 A-Za-z,数字 0-9 和空格。

小 P 在这些字符上定义了一个字符替换函数 f(ch)f(ch),表示把字符 chch 替换成 f(ch)f(ch)

例如,若 f(a)=bf(a)=b,则字符 a 会被替换成 b;若 f(b)=0f(b)=0,则字符 b 会被替换成 0

在字符替换的基础上,定义字符串变换函数 F(s)F(s):将字符串 ss 中的每个字符 chch 都替换为 f(ch)f(ch)

字符替换函数 ffnn 个字符对 (ch1,ch2)(ch_1,ch_2) 给出,表示:

f(ch1)=ch2f(ch_1)=ch_2

并满足以下条件:

  • 所有字符对中的 ch1ch_1 两两不同,即同一个字符不会被定义两种不同的替换方式;
  • 如果某个字符 chch 没有在输入中定义,则认为 f(ch)=chf(ch)=ch,即该字符保持不变;
  • 函数 ff 是单射,即不同字符不会被替换成同一个字符。

现在给定初始字符串 ss,需要处理 mm 个查询。

每个查询给出一个正整数 kk,要求输出对初始字符串 ss 连续执行 kk 次字符串变换后的结果:

Fk(s)F^k(s)

输入格式

从标准输入读入数据。

输入共 n+4n+4 行。

第一行输入一个形如 #s# 的字符串,即使用两个井号 # 将初始字符串 ss 包围起来。

第二行输入一个正整数 nn,表示字符替换规则的数量。

接下来的 nn 行,每行输入一个形如:

#xy#

的字符串,表示:

f(x)=yf(x)=y

n+3n+3 行输入一个正整数 mm,表示查询数量。

最后一行输入 mm 个由空格分隔的正整数:

k1,k2,,kmk_1,k_2,\cdots,k_m

分别表示 mm 次查询要求的变换次数。

输出格式

输出共 mm 行。

对于每个查询,输出字符串经过相应次数变换后的结果。

每一行仍使用两个井号将结果字符串包围,即输出形式为:

#s#

样例
输入
#Hello World#
6
#HH#
#e #
# r#
#re#
#oa#
#ao#
3
1 2 3
输出
#H llarWaeld#
#HrlloeWo ld#
#Hella Warld#
子任务

60%60\% 的测试数据满足:

  • 初始字符串 ss 只包含小写字母;
  • 输入的字符替换规则也只涉及小写字母,即小写字母只会被替换成小写字母。

80%80\% 的测试数据满足:

m10,k100m\le10,\qquad k\le100

全部测试数据满足:

0<n63,0<m103,0<k1090<n\le63,\qquad 0<m\le10^3,\qquad 0<k\le10^9

并且初始字符串 ss 的长度不超过 100100

提示

由于输入字符串中可能包含空格,因此读入字符串时应当使用能够读取整行的方法,而不能直接使用会跳过空格的普通字符串读入方式。

C++ 中推荐使用:

getline(cin, s);

Python 可以直接使用:

input()

题解

这道题目放在第2题是相对简单的一道,很容易 AC。

主要需要注意到,对全部的测试数据,kk 是能够取到 10910^9 的数量级的,说明这道题不能够完全遵循题意去搞模拟,不然只能过 80%80\% 的测试点。

注意到此题的字符变换有周期性,可以写成环的形式,例如样例:

  • H -> H
  • e -> <blank> -> r -> e
  • <blank> -> r -> e -> <blank>
  • r -> e -> <blank> -> r
  • o -> a -> o
  • a -> o -> a

根据这个性质,就可以不借助模拟,通过取模直接得到各字符在一定次数 kk 次变换后的结果,给出代码如下:

#include <iostream>
#include <string>
#include <unordered_map>

using namespace std;

int n, m;
unordered_map<char, string> f;
unordered_map<char, char> r;

int main() {
    string s;
    getline(cin, s);
    
    cin >> n;
    cin.ignore();
    
    // init
    for(char ch = 'a'; ch <= 'z'; ch ++) {
        f[ch] += ch;
    }
    for(char ch = 'A'; ch <= 'Z'; ch ++) {
        f[ch] += ch;
    }
    for(char ch = '0'; ch <= '9'; ch ++) {
        f[ch] += ch;
    }
    f[' '] += ' ';

    // read basic relation
    while(n --) {
        string p;
        getline(cin, p);
        r[p[1]] = p[2];
    }
    
    // transmit
    for(const auto& kv : r) {
        if (kv.first != kv.second) f[kv.first] += kv.second;
        char t = kv.second;
        while(r.count(t) && r[t] != kv.first) {
            f[kv.first] += r[t];
            t = r[t];
        }
    }
    
    cin >> m;
    cin.ignore();
    
    while(m --) {
        int k;
        cin >> k;
        
        for(const char& ch : s) {
            if(f.count(ch)) {
                string str = f[ch];
                cout << str[k % str.length()];
            }
            else cout << ch;
        }
        
        cout << "\n";
    }
    
    return 0;
}