字符串变换

时间限制: 1.0 秒

空间限制: 512 MiB

相关文件: 题目目录(样例文件)

题目描述

本题涉及字符包括大小写字母(A-Za-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(b0 都被替换为 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;
}

没有测试过,可以测测,有问题各路神仙,记得留言呀!!!!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值