hud 4300 扩展kmp

题目大意:多组数据

               第一行是一个含有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

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-1p 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-1p 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

hud 4300 扩展kmp_第1张图片


你可能感兴趣的:(模板,kmp&extend-kmp)