字符串专题
1、字符串还原 restore
【问题背景】 小K是一位蔚蓝教主的崇拜者(Orz教主er),有一天,他收到了一封匿名信,信告诉了小K由于他表现出色,得到了一次当面Orz教主的机会,但是要当面 Orz教主可不那么容易,不是每个人都有资格Orz教主的……所以要破解下面一段密文才可以得到相关的信息,信中有提供加密的规则,但是小K觉得这个问题 看似复杂,所以想请你帮忙…… 【问题描述】 一个长度为n的由小写字母组成的字符串s1s2…sn按如下方式加密成3种形式: 1、 将字符串翻转,即s(i)与s(n-i+1)对换。 2、 将字符串中每个字母变为其之后第k个字母,定义z之后的字母为a,0≤k≤6且未知。 3、 将字符串中每个字母变为其之前第k个字母,定义a之前的字母为z,k同2。 例如字符串abcd按上面3种方式加密后,在k=1的情况下为:1、dcba;2、bcde;3、zabc。 现给出信中按以上3种形式分别加密后的3个字符串(不一定按以上顺序),要求还原原来的字符串,并输出告诉小K。 【输入格式】 输入文件restore.in的第1行为一个整数n,表示这个字符串的长度。 下面3行每行3个长度为n的字符串,且保证符合题目要求。 【输出格式】 输出文件restore.out仅包括1行,为还原后的字符串。 【样例输入】 4 zabc dcba bcde 【样例输出】 abcd 【数据规模】 对于10%的数据,输入给出加密字符串的顺序同题目中1、2、3的顺序。 对于20%的数据,n≤5; 对于40%的数据,n≤10; 对于60%的数据,n≤255; 对于100%的数据,n≤10000。 |
||
老师题解:
可以转化为找到翻转加密的串逆序输出即可,另外2个串肯定满足所有对应第i位字母差(a转为0,b转为1,类推)相同(利用26个字母,k<=6,求出当差绝对值大于6可以对应成小于6的),如果翻转串也满足以上条件,那么原串为回文串。在k>0的情况下满足与其余2个串满足上述条件且差相等或者不满足上述条件即为翻转串,逆序输出,这样只要两两判断1次即可。
由于vijos承受不了大规模数据,n改成10000后枚举顺序和k等等都是不错的方法。
时间复杂度O(n)
我的[程序]:
1 program p1850; 2 var 3 n,i,k:longint; 4 s1,s2,s3:ansistring; 5 ch:char; 6 function change1(s:ansistring):ansistring; 7 begin 8 for i:=1 to n div 2 do 9 begin 10 ch:=s[i]; 11 s[i]:=s[n-i+1]; 12 s[n-i+1]:=ch; 13 end; 14 change1:=s; 15 end; 16 function change2(s:ansistring):ansistring; 17 begin 18 for i:=1 to n do 19 if (ord(s[i])+k)>ord('z') then s[i]:=chr(ord('a')+ord(s[i])+k-ord('z')-1) 20 else s[i]:=chr(ord(s[i])+k); 21 change2:=s; 22 end; 23 function change3(s:ansistring):ansistring; 24 begin 25 for i:=1 to n do 26 if (ord(s[i])-k)<ord('a') then s[i]:=chr(ord('z')-(ord('a')-(ord(s[i])-k))+1) 27 else s[i]:=chr(ord(s[i])-k); 28 change3:=s; 29 end; 30 begin 31 readln(n); 32 readln(s1); readln(s2); readln(s3); 33 for k:=0 to 6 do 34 begin 35 //write(change1(s2),' '); write(change3(s3),' '); write(change2(s1)); writeln; 36 if (change1(s1)=change2(s2))and(change2(s2)=change3(s3)) then 37 writeln(change1(s1)) else 38 if (change1(s1)=change2(s3))and(change2(s3)=change3(s2)) then 39 writeln(change1(s1)) else 40 if (change1(s2)=change2(s1))and(change2(s1)=change3(s3)) then 41 writeln(change1(s2)) else 42 if (change1(s2)=change2(s3))and(change2(s3)=change3(s1)) then 43 writeln(change1(s2)) else 44 if (change1(s3)=change2(s1))and(change2(s1)=change3(s2)) then 45 writeln(change1(s3)) else 46 if (change1(s3)=change2(s2))and(change2(s2)=change3(s1)) then 47 writeln(change1(s3)) else 48 end; 49 end.
2、古韵之同心锁
【题目描述】 纤云弄巧,飞星传恨,银汉迢迢暗度。金风玉露一相逢,便胜却人间无数。 柔情似水,佳期如梦,忍顾鹊桥归路。两情若是久长时,又岂在朝朝暮暮! ——秦观《鹊桥仙》 夜未央。带着细腻连绵的眼光遥望牛郎织女千年的爱情,平淡、精致且长久的幸福感顿时氤氲在心。或许幸福就是这样,不求朝暮合,但求永同心。据说同心锁是恋人们定情的一种信物,上面刻着两人的名字,它见证着天长地久的爱情,诉说着爱情的坎坷与甜蜜。 据说在一座OI桥上,同心锁上显示的文字有着它奇异的呈现方式,需要你把它稍做改变才可解密。每个同心锁上都有3个数据。第一个数据是一个字符串s。 第二个数据m表示把s串从m处分为两段,s[1]至s[m-1]为a串,s[m]至最后为b串。第三个数据n表示你需要做改变的方式。第4个数据表示把n 处理后的s串每个字母变重复次数p,不用重复则为0。 当n=1时,把s串中所有大写字母改成小写字母,把所有小写字母改成大写字母,然后在后面加上‘Immorta1’; 当n=2时,从s串中删除所有出现的和b一样的子串,然后把所有出现的‘1013’改成‘hh4742’。 当n=3时,在a串部分的|n-m|-1和|n-m|之间插入b串,并删除b串部分。 【输入格式】 第一行有一个字符串s(长度不超过1993); 第二行有3个数:m(1<m<s的长度)、n(1、2或3)、p(0<=p<100)。 【输出格式】 输出一个字符串,为经过多次变化后最终得到的s。 【样例输入1】 MEIYOUwsshujuBYhh4742 14 1 1 【样例输出1】 mmeeiiyyoouuWWSSSSHHUUJJUUbbyyHHHH44774422IImmmmoorrttaa11 【样例输入2】 oiBYhh4742MEIYOU1013hh4742wsshujuBYhh4742 34 2 0 【样例输出2】 oiMEIYOUhh4742hh4742wsshuju 【样例输入3】 ipkepk 5 3 3 【样例输出3】 iiiippppkkkkppppkkkkeeee |
||
老师题解:
字符串处理问题,题目不是很难,考的是细节。主要是注意插入和替换的位置。其他没有什么问题。
我的[程序]:
1 program p1851; 2 var 3 s,a,b,c,d:ansistring; 4 m,n,p,i,j,l,la,lb:longint; 5 begin 6 readln(s); 7 read(m); read(n); readln(p); 8 if m=1 then 9 begin 10 l:=length(s); la:=1; lb:=l-1; 11 a:=copy(s,1,la); 12 b:=copy(s,2,lb); 13 end else 14 begin 15 l:=length(s); la:=m-1; lb:=l-m+1; 16 a:=copy(s,1,la); 17 b:=copy(s,m,lb); 18 end; 19 if n=1 then 20 begin 21 for i:=1 to l do 22 if (ord(s[i])>=65) and (ord(s[i])<=90) then s[i]:=lowercase(s[i]) 23 else 24 if (ord(s[i])>=97) and (ord(s[i])<=122) then s[i]:=upcase(s[i]); 25 s:=s+'Immorta1'; 26 inc(l,8); 27 end; 28 if n=2 then 29 begin 30 while pos(b,s)<>0 do 31 begin 32 delete(s,pos(b,s),lb); 33 dec(l,lb); 34 end; 35 c:='1013'; d:='hh4742'; 36 while pos(c,s)<>0 do 37 begin 38 insert(d,s,pos(c,s)); 39 delete(s,pos(c,s),4); 40 inc(l,2); 41 end; 42 end; 43 if n=3 then 44 begin 45 insert(b,s,abs(n-m)); 46 delete(s,la+lb+1,lb); 47 end; 48 for i:=1 to l do 49 for j:=1 to p+1 do 50 write(s[i]); 51 end.
3 .牛的RP
【问题描述】 天苍苍,野茫茫,JSZX的菜鸟们来到OI牧场旅游,看到了好多好多的牛。OI牧场所有的牛都觉得自己的Rp最高(简称RP牛),为此他们常争论不休。于是,他们让JSZX的菜菜们用最最朴素的方法找出这只RP牛。 经过讨论,最菜的mmk想出了最朴素的方法: 我们要以cows的名字为线索,来找出RP牛。 首先,得到n头牛的名字清单(每头牛的名字是一个仅包含小写字母的字符串,且这些牛的读写方式比较特殊—从右到左),然后对每头牛进行检验,检验按照牛的读写方式进行。规则如下: 1.Rp 牛的名字中必须有子串“jszxoier” 2.将名字中的每个“cow”的替换为“bird”。 3.计算Rp值:A为名字中子串“r”的个数; B为名字中子串“p”的个数; C为名字中字串“rp”的个数; Rp值即为5×A+5×B+20×C。 最后输出RP牛的名字,若有多个RP牛,则输出名字最短的那个。 假如你也是牛中一员,尽管你很不屑这样的水题,但是,你很想到RP牛那里分点Rp,所以你决定解决这道题,并算出RP牛的Rp是多少。 【输入】 第一行,一个数n(n<=3000)。 接下来的n行,每行一个字符串,长度<=600,数据保证存在RP牛。 【输出】 共两行 第一行为RP牛的名字 第二行为RP牛的Rp值 【样例输入】 8 reioxzsjzmy mmk jwc zxf jwc wangwei xcy yuhc 【样例输出】 reioxzsjzmy 5 |
|||