字符串专题

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.
restore

 

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.
lock

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
     

 

   
posted @ 2015-10-19 12:41  ZJQCation  阅读(613)  评论(0编辑  收藏  举报