时间限制: 1.0 秒
空间限制: 512 MiB
相关文件: 题目目录(样例文件)
题目描述
本题涉及字符包括大小写字母(A-Z
和 a-z
)、数字(0-9
)和空格共 6363 种。在这个字符集合上,小 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),表示对字符串 s
进行变换,将 s
中每个字符 chch 都替换为 f(ch)f(ch)。
字符替换函数 ff 可表示为 nn 个字符对 (ch1,ch2)(ch1,ch2),即 f(ch1)=ch2f(ch1)=ch2。
-
nn 个字符对中,ch1ch1 两两不同,即不会出现同时定义了 f(a)=bf(a)=b 和 f(a)=0f(a)=0 的情况;
-
未定义的 f(ch)f(ch),可视为 f(ch)=chf(ch)=ch,即字符 chch 保持不变;
-
函数 ff 为单射,即当 ch1≠ch2ch1=ch2 时有 f(ch1)≠f(ch2)f(ch1)=f(ch2),例如不会同时有 f(b)=0f(b)=0 和 f(0)=0f(0)=0(
b
和0
都被替换为0
)。
现给定初始字符串 s
,试处理 mm 个查询:每个查询包含一个正整数 kk,询问对初始字符串 s
变换 kk 次后的结果 Fk(s)Fk(s)。
输入格式
从标准输入读入数据。
输入共 n+4n+4 行。
输入的第一行包含一个字符串,形如 #s#
,即用两个井号字符 #
将初始字符串 s
囊括其中。
输入的第二行包含一个正整数 nn,表示组成函数 ff 的字符对数;接下来 nn 行每行输入一个形如 #xy#
的字符串,表示 f(x)=yf(x)=y。
输入的第 n+3n+3 行包含一个正整数 mm,表示查询的个数;下一行包含空格分隔的 mm 个正整数 k1,k2,⋯ ,kmk1,k2,⋯,km,表示 mm 个查询。
输出格式
输出到标准输出。
输出共 mm 行,依次输出 mm 个查询的结果;输出时每行同样是一个形如 #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;
全部测试数据保证 0<n≤630<n≤63、0<m≤1030<m≤103、0<k≤1090<k≤109 且初始字符串 s
包含不超过 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()
函数即可读入整行。
#include<bits/stdc++.h>
using namespace std;
/*
1.进行变换的时候怎样存储字符串对应的关系
2.没有的变换就是他自己本身
3.用链表来存储吗?
//set集合肯定不行
4.用结构体?
pair但是查询很多次
5.用链表吗?循环链表?
6.我怎样知道他是不是走到头了,就是有没有找到他的双亲?
7.加入一个数据的时候,p的child固定,但child的child都开始初始化为空,一直循环即可,是不是可以统计然后做
8.需要有一个头节点吗?
*/
int chan(char ch){
if(ch>='A'&&ch<='Z'){
return ch-'A'+1; //1到26
}
else if(ch>='a'&&ch<='z'){
return ch-'a'+27;//27到52
}
else
{
return 53;//空格字符
}
}
struct node{
char ch;//他自己的编号,用指针连接
struct node *child;//孩子的编号,只有一个孩子,单线循环链表
int flag;//表明他的组号,若是新添加的这个组的flag与当前这个flag相同的话,就是一圈了
int total;//这一组的个数
int huan;//1表明他是一个环,0则不是一个环
};
struct node *da[100];//结构体的个数,也就是所有字母开头
int zu[100];//组号对应的这一个环具有的个数
void tran(string str,int p);
int main(){
int n;
string str0;
getline(cin,str0);
memset(zu,1,sizeof(zu));//初始化都为1个
for(int i=0;i<99;i++){
da[i]=(struct node*)malloc(sizeof(struct node));
}
//将这些字符串作为根节点开始建立链表
for(int i=0;i<60;i++){
if(i>=1&&i<=26){
da[i]->ch=i+'A'-1;
}
else if(i>=27&&i<=52){
da[i]->ch=i+'a'-27;
}
else{
da[i]->ch=' ';//空格字符
}
da[i]->child=NULL;//初始化为0
da[i]->total=1;
da[i]->huan=0;//不是一个环
da[i]->flag=i;//他的组号
}
//cin>>str;//输入字符串
//从第一个字符串一直读到倒数第二个字符
cin>>n;//进行变换的次数规定的格式
//怎样进行变换呢
getchar();//读取空格
string str;
for(int i=0;i<n;i++){ //将他们连成了一个环状
getline(cin,str);
// cout<<"gandu shchu"<<str<<endl;
int u=chan(str[1]);//父节点
int v=chan(str[2]);//孩子节点
da[u]->ch=str[1];//初始化
da[v]->ch=str[2];
da[u]->child=da[v];//链表的连接
//定义此时孩子的号不再改变,他是这一组的标记
if(da[u]->flag==da[v]->flag)//如果组号相同就是一个环
{
da[v]->huan=1;//是一个环,v应该是代表的是组号
}
else{//他们之前不是一个环的
int h=da[u]->flag;
da[v]->flag=h;//合并为一组
zu[h]++;//添加一个成员,个数加一
}
}
int m,q;
cin>>m;//需要变换的次数
//进行查询
for(int i=0;i<m;i++){
cin>>q;
//进行变换
tran(str0,q);
}
}
void tran(string str,int p){
string reslut;//最后的结果
//一个字符的变换
reslut+='#';
int x=p;//用于迭代
for(int i=1;i<str.length()-1;i++){
//第一种他没有孩子,只有他自己
//有孩子但是单链,已经为空最后的字符
//单链,次数没超过
//环状,从开始的字符进行child,求余运算减少次数
x=p;
int u=chan(str[i]);//对应的结构体
if(da[u]->child==NULL){
reslut+=str[i];
}
else if(da[u]->flag==0){//有孩子,是单链
struct node *tmp=da[u];
int y=0;
while(x--){//查询x次
tmp=tmp->child;//向下查询,直到x次的时候才会终止
if(tmp->child==NULL){
reslut+=tmp->ch;
y==1;
break;//直接结束
}
}
if(y==0){
reslut+=tmp->ch;
}
}
else{//有孩子而且还是环状
int w=da[u]->flag;//他的组号
int num=zu[w];//他这一组的个数
x=p%num;//从当前的字符开始向后走x格
struct node *tmp=da[u];
while(x--){
tmp=tmp->child;
}
reslut+=tmp->ch;
}
}
reslut+='#';
cout<<reslut<<endl;
}
没有测试过,可以测测,有问题各路神仙,记得留言呀!!!!!!