CCF认证-202409-02 | 字符串变换

题目描述

本题涉及字符包括大小写字母(A-Z 和 a-z)、数字(0-9)和空格共 63 种。在这个字符集合上,小 P 定义了一个字符替换函数 f(ch),表示将字符 ch 替换为 f(ch)。 例如 f(a)=b 表示将 a 替换为 b,f(b)=0表示将 b 替换为 0。 进而可以将其扩展为字符串变换函数 F(s),表示对字符串 s 进行变换,将 s 中每个字符 ch 都替换为 f(ch)。

字符替换函数 f 可表示为 n 个字符对 (ch1​,ch2​),即 f(ch1)=ch2​。

  • n 个字符对中,ch1​ 两两不同,即不会出现同时定义了 f(a)=b 和 f(a)=0 的情况;

  • 未定义的 f(ch),可视为 f(ch)=ch,即字符 ch 保持不变;

  • 函数 f 为单射,即当 ch1≠ch2 时有 f(ch1)≠f(ch2),例如不会同时有 f(b)=0 和 f(0)=0(b 和 0 都被替换为 0)。

现给定初始字符串 s,试处理 m 个查询:每个查询包含一个正整数 k,询问对初始字符串 s 变换 k 次后的结果 Fk(s)。

输入格式

从标准输入读入数据。

输入共 n+4 行。

输入的第一行包含一个字符串,形如 #s#,即用两个井号字符 # 将初始字符串 s 囊括其中。

输入的第二行包含一个正整数 n,表示组成函数 ff 的字符对数;接下来 n 行每行输入一个形如 #xy# 的字符串,表示 f(x)=y。

输入的第 n+3 行包含一个正整数 m,表示查询的个数;下一行包含空格分隔的 m 个正整数 k1,k2,⋯,km​,表示 m 个查询。

输出格式

输出到标准输出。

输出共 m 行,依次输出 m 个查询的结果;输出时每行同样是一个形如 #s# 的字符串,即用两个井号把变换后的字符串 s 括起。

样例输入

#Hello World#
6
#HH#
#e #
# r#
#re#
#oa#
#ao#
3
1 2 3

样例输出

#H llarWaeld#
#HrlloeWo ld#
#Hella Warld#

子任务

前 6060 的测试数据保证初始字符串 s 仅包含小写字母,且输入的 nn 个字符对也皆为小写字母(即保证小写字母仅会被替换为小写字母);

前 8080 的测试数据保证查询数量 m≤10m≤10、变换次数 k≤100k≤100;

全部测试数据保证 0s 包含不超过 100 个字符。

提示

由于读入的字符串中包含空格字符,推荐使用按行读取的方式,避免读入时跳过空格(如 cin 直接读入字符串)。

C 语言:可以使用 fgets() 函数读入整行,fgets(s, count, stdin) 会从标准连续输入读入至多 count - 1 个字符,并存入字符数组 s,直到遇到换行符或文件末尾为止。在前一种情况下,s 结尾处会存有读入的换行符。也可使用 getchar() 函数逐个字符读入,如 char ch = getchar();,这种方法需手动判断是否到达行末,即返回值是否为 \n

C++:可以使用 std::getline() 函数读入整行:std::getline(std::cin, s) 会从标准输入读入字符,并存入字符串 std::string s 中,直到换行符或文件末尾为止。在前一种情况下,换行符会从标准输入中读出,但不会存入字符串 s 中。

Python:使用 input() 函数即可读入整行。

题解:

        刚看完题,就感觉给的单射一定能形成循环,否则当k是1e9肯定超时。

        开始解题,关于如何替换字符串,使用一个的map记录单射,循环原串就可以得到转化一次后的新字符串。

        所以第一种解法就是蛮力求解,循环k,每循环一个就从头开始循环原串,输出,得到80分(前面的给的是真宽泛),时间效率O(N3)。

        想怎么优化,因为CCF给的空间达到了512M,所以空间非常充足,以空间换时间是很好的办法,于是有了第二种方法。建一个新的 的map,先取得k的最大值,然后变换k次,每次把得到的string和次数放进map里,最后遍历一遍k输出string就可以了,得到80分,但是时间优化到了O(N2)。

        那怎么办呢,于是就再牺牲一下空间并考虑一下循环的事了。

        说到循环,很简单的方法就是记录循环的次数然后取模即可,但是你怎么知道循环从哪开始,题目也没说一定全部都是循环,所以从原串开始变换,并压入一个新的map并记录变换的次数(代码是用了一个vector记录,原理一样),然后当遇到重复的就去map里找,得到开始重复的次数,当k<=这个数就直接输出,当k>这个数时就取模后加上序号即可,得分90,时间O(N),但是仍然有两个数据集出现了奇怪的问题(还没搞明白)。

        但是对于解题,我们已经搞定了数据集最大的那几个,那就结合第二种和第三种方法,就成功得到了100啦!虽然很可耻……

代码:

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;

string s;
int n=0,i,j,t,t1;
string op[1001]={""};
int m=0;
int k[10001]={0};
vector  v;
map mp;
map mpp;
map maa;
vector  vt;
int maxk=0;

int cmp(int x,int y){
    return x> n;
    getchar();
    for(i=0;i> m;
    for(i=1;i<=m;i++){
        cin >> k[i];
        if(k[i]>maxk){
            maxk=k[i];
        }
        mpp[k[i]]="";
    }
    //cout << maxk << "\n";
    maa[s]=1;vt.push_back(s);
    //maxk=100;
    if(m>=11){
        for(i=1;i<=maxk;i++){
                /*
            for(t=0;t

你可能感兴趣的:(算法,动态规划,线性代数,数据结构)