Automatic Editing题解
7月28的考试题鸭
大致翻译(可能不太准,但题意一样,至少我过了)
问题描述: 为了对一些资料进行保密,奶牛们要对某些文章进行编辑。编辑的方法很奇特:要把原有文章 的某些词句按照某些规则用另 规则的形式如下:原串 新串,表示把原串替换成 新串。
假设有 n 条规则,第 i 规则的原串和 新串分别为 Mi 和 Ni,则编辑按如下过程进行:
开始编辑时,先使用第一条规则,把文章中出现的 第一个 M1 替换成 N1,如果替换后的新文章还存在 M1,则如上处理,直到文章不存在 M1 为止;
然后用同样的方法使用第 2,第 3,……,第 n 条 规则进行替换,直到所有的规则都用完为止。
注意: 1、 每次都要从文章开头开始找要替换的词句 2、一条规则一旦使用完后,将不能再使用 3、 每一篇文章都是可编辑的 如有四条规则:
ban——>bab(1)
baba——>be(2)
ana——>any(3)
ba b——>hind the g(4)
要编辑的文章为“banana boat ,则编辑的过程如下: 编辑顺序 编辑前的文章 编辑后的文章 使用的规则:
banana boat——>babana boat (1)
babana boat——>bababa boat (1)
bababa boat——>beba boat (2)
(第三个规则没用到)
beba boat——>behind the goat (4)
编辑后的文章为“behind the goat”。请编写一程序,帮助组委会对给定的文章进行编辑。 输入格式:
可能有一组到多组数据,每组共有 2n+2 行。第一行是一个整数 n(1<=n<=10),表示规则的数目;接下来第 2i行及第 2i+1 行分别表示 Mi 和 Ni(1<=i<=n),其长度均不超过 80 个字符,且 Mi 不为空串;最 后一 行是要编辑的文章,长度不超过 80 个字符。行末没有空格。读入到0时截止
输出格式: 文件只有一行,表示编辑后的文章(长度不超过 80 个字符)。行末也应该没有空格。
蒟蒻动手写的第一篇题解hhhh
作为第一个在洛谷通过这道题的人!!!虽然找了无数大佬
好吧我们进入正文:
这道题其实不难,纯模拟无算法,数据也小能暴力,但最重要的就是要注意细节鸭。
优化可以用链表,但我太懒了就算了吧
PPPPPPPPS:
不要问我为什么我的输入是这个亚子的奇怪,因为这道题就是卡你的输入输出xixi
话不多说,代码里详细解释:
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 int n=1; 5 char first[50001],rule[105][3][201];//数组不用开这么大,但我刚开始出现了RE xixi 6 7 int main() 8 { 9 //freopen("editing.in","r",stdin); 10 //freopen("editing.out","w",stdout); 11 while(n!=0)//程序结束的条件 12 { 13 scanf("%d",&n); 14 getchar();//不要问我为什么!!! 15 if(n==0) 16 return 0; 17 for(int i=1;i<=n;i++) 18 { 19 scanf("%[^\n]",rule[i][0]),getchar();//相当于题目中m[i] 20 scanf("%[^\n]",rule[i][1]),getchar();//n[i] 21 } 22 scanf("%[^\n]",first); 23 getchar();//同上 24 for(int i=1;i<=n;i++)//n条规则 25 { 26 int iff=1;//用iff表示第i条规则是否还要“继续判断”使用 27 while(iff) 28 { 29 iff=0; 30 //进入while后,先定义iff为0防止跑到停不下来 31 int len=strlen(first),l=strlen(rule[i][0]); 32 for(int j=0;j+l-1<len;j++)//循环,找与规则[i]相同的数组,注意长度 33 { 34 int flag=1;//用flag表示第i 条规则“能否”使用 35 for(int k=j;k<=j+l-1;k++) 36 { 37 if(first[k]!=rule[i][0][k-j]) 38 { 39 flag=0;//若有一个字符不同则不能使用这一条规则 40 break; 41 } 42 } 43 if(flag)//修改 44 { 45 //注意rule[i][1]与rule[i][0]的长度可能不同 46 //所以要将修改后位置不对的字符移动(应该能看懂) 47 if(strlen(rule[i][1])>=l) 48 { 49 int w=strlen(rule[i][1])-l; 50 if(w) 51 for(int p=len-1;p>j+l-1;p--) 52 first[p+w]=first[p]; 53 for(int p=0;p<strlen(rule[i][1]);p++) 54 first[j+p]=rule[i][1][p]; 55 } 56 else 57 { 58 int w=-strlen(rule[i][1])+l; 59 for(int p=j+l;p<=len-1;p++) 60 first[p-w]=first[p]; 61 for(int p=0;p<strlen(rule[i][1]);p++) 62 first[j+p]=rule[i][1][p]; 63 for(int p=1;p<=w;p++) 64 first[len-p]='\0';//后面多出的字符定义为‘\0’,不然会导致输出错误 65 } 66 iff=1; 67 //如果本次能修改就要判断下次能否修改 68 //如果本次不能修改则表示这条规则不能再使用(因为循环是跑到底的) 69 break; 70 } 71 } 72 } 73 } 74 printf("%s\n",first); 75 memset(first,'\0',sizeof(first)); 76 memset(rule,'\0',sizeof(first));//因为有多组数据所以要初始化 77 } 78 return 0;//完美结束(大呼爽快) 79 }
PPPPPPPPPPPPPS+1:
关于scanf的这个奇怪还很丑的用法呢,介个还是粗略讲下吧。
在"%"后连接上的中括号中,可以写上输入的范围(输入到不是范围的字符就会退出输出),举个栗子,%[a-z]是范围设为小写字母,%[^(1-9)]表示不输入1~9这个区间内的字符(^可以理解为不取嘛)。
所以"%[^\n]"的用法就是不输入换行啦(而且可以输入空格!!!)
结束!
PPPPPPPPPPPPPS+2:
这道题其实不难,个人认为在黄题左右(其实我也不确定,个人感觉)
但就是因为输入输出,我调了一下午加半个晚自习(调到脑袋爆炸)
PPPPPPPPPPPPPS+3:
感谢dalao的帮助 hyc