hud 4300 扩展kmp

来源:互联网 发布:网络系统集成就业前景 编辑:程序博客网 时间:2024/04/27 23:52

题目大意:多组数据

               第一行是一个含有26个字母的字符串,即翻译表,表示字母表(a、b、c……)中第i个字母对应的密文是s1[i]

               第二行是一个另一个字符串s3,前面为密文后面为明文,密文一定是完整的, 明文可能不完整或没有

               输出完整的密文和完整的明文

那么我们就把s3全部当做密文,根据翻译表s1全部翻译成明文s2,

这样,原来s3前面的密文就变成了明文,后面的明文变成什么对我们没有影响

显然,此时s2前面明文部分与s3的后面的明文部分应该是相同的

所以,我们应采用扩展kmp的方法,

将s3看做母串S,s2看做子串T,进行扩展kmp

从 len/2开始枚举找到第一个i+exten[i]-1=len 且 i>=extend[i] 的位置作为明文的第一个字母,之前的即为密文,对应的即为明文

注意各种特例及细节:

1、可能没有明文,那么此时i会停止在len位置,即s3[1~len]全为密文而不是i之前的子串,所以我们在通过上面的方法确定出i位置后,判断s3[i]对应的密文与s3[1]是否相等,如果相等即s3[1~i-1]为密文,否则s3[1~i]为密文

2、密文的长度一定不小于len/2,在判断s3[i]对应的密文与s3[1]是否相等时,恰好相等,但是i-1<len/2即i-1作为密文最短长度不成立,那么最短长度应该是i

3、对于长度为1的情况的特判

总之不注意细节各种崩溃,不注意边界的特判各种坑,非常感谢讨论区倩同学提供的数据 orz

7

qwertyuiopasdfghjklzxcvbnm

qwert

qwertyuiopasdfghjklzxcvbnm

qwerta

qwertyuiopasdfghjklzxcvbnm

q

abcdefghijklmnopqrstuvwxyz

aaaa

abcdefghijklmnopqrstuvwxyz

aaa

abcdefghijklmnopqrstuvwxyz

aa

abcdefghijklmnopqrstuvwxyz

a

代码:

var        t,len           :longint;        s1,s2,s3,ans    :ansistring;        i,j,k           :longint;        ch              :char;        next,extend     :array[0..100010] of longint;procedure get_next;var        a,p,l:longint;        j,k:longint;begin   next[1]:=len;a:=0;   while (a+2<=len) do    if (s2[a+1]=s2[a+2]) then inc(a) else break;   next[2]:=a;a:=2;   //   for k:=3 to len do   begin      p:=a+next[a]-1;l:=next[1+k-a];      if (k+l-1<p) then next[k]:=l else      begin         if p-k+1<0 then j:=0 else j:=p-k+1;         while (k+j<=len) and (j+1<=len) do          if (s2[k+j]=s2[j+1]) then inc(j) else break;         next[k]:=j;         if k+next[k]-1>p then a:=k;      end;   end;end;procedure get_extend;var        a,p,l:longint;        j,k:longint;begin   get_next;   a:=0;   while (a+1<=len) do    if (s2[a+1]=s3[a+1]) then inc(a) else break;   extend[1]:=a;a:=1;   //   for k:=2 to len do   begin      p:=a+extend[a]-1;l:=next[1+k-a];      if (k+l-1<p) then extend[k]:=l else      begin         if p-k+1<0 then j:=0 else j:=p-k+1;         while (j+k<=len) and (j+1<=len) do          if (s3[j+k]=s2[j+1]) then inc(j) else break;         extend[k]:=j;         if k+extend[k]-1>p then a:=k;      end;   end;end;begin   readln(t);   while (t>0) do   begin      dec(t);      fillchar(next,sizeof(next),0);      fillchar(extend,sizeof(extend),0);      readln(s1);      readln(s3);      len:=length(s3);      if len=1 then      begin         write(s3);         for i:=1 to 26 do          if s3[1]=s1[i] then          begin             writeln(chr(96+i));break;          end;      end else      begin         s2:='';         for i:=1 to len do          for k:=1 to 26 do           if (s3[i]=s1[k]) then           begin              s2:=s2+chr(96+k);break;           end;         get_extend;      //         for i:=len div 2 to len do          if (i+extend[i]-1=len) and (i>=extend[i]) then break;         ch:=s1[ord(s3[i])-96];         if (ch=s3[1]) and ((i-1)*2>=len) then         begin            ans:=copy(s3,1,i-1);            ans:=ans+copy(s2,1,i-1);         end else         begin            ans:=copy(s3,1,i);            ans:=ans+copy(s2,1,i);         end;         writeln(ans);      end;   end;end.
——by Eirlys



0 0
原创粉丝点击