描述 Description

给你两个串A,B,可以得到从A的任意位开始的子串和B匹配的长度。
给定K个询问,对于每个询问给定一个x,求出匹配长度恰为x的位置有多少个。
N,M,K<=200000

输入格式 Input Format

第一行三个数 N,M,K,表示A的长度、B的长度和询问数。
第二行为串A。
第三行为串B。
接下来K行,每行1个数X。

输出格式 Output Format

对于每个询问输出一个数。

分析:

      需要处理的问题有:

      1.需要的是长度恰好为x的,而不是可以达到x的

      2.kmp中一些没有匹配过的字符的处理。如 aba和ab,就不会有从aba中的b开始匹配的时候

      对于问题1,可以只记录能匹配x长度的数量(数组q),而恰好匹配x的值就是q[x]-q[x+1]

      对于问题2,可以应用p数组(next),如果第i个长度可以匹配,那么p[i]也可以匹配,所以把ans[i]的值加到ans[p[i]]上

code

program haha;
var
   a,b	     : ansistring;
   p,ans,q   : array[0..200002] of longint;
   i,j,m,n,k : longint;
procedure init;
begin
   readln(n,m,k);
   readln(a);
   readln(b);
   j:=0;
   for i:=2 to m do
   begin
      while (j>0) and (b[j+1]<>b[i]) do j:=p[j];
      if b[j+1]=b[i] then
	 inc(j);
      p[i]:=j;
   end;
end; { init }
procedure work;
var
   K : longint;
begin
   j:=0;
   for i:=1 to n do
   begin
      while (j>0) and (b[j+1]<>a[i]) do
	 j:=p[j];
      if b[j+1]=a[i] then
	 inc(j);
      if j=m then
	 j:=p[j];
      q[i]:=j;//记录主串中在匹配串中匹配的长度
   end;
   for i:=1 to n do
      inc(ans[q[i]]);
   for i:=m downto 1 do
      inc(ans[p[i]],ans[i]);
end; { work }
begin
   assign(input,'sdf.in'); reset(input);
   //assign(output,'sdf.out'); rewrite(output);
   init;
   work;
   for I:=1 to k do
   begin
      readln(n);
      writeln(ans[n]-ans[n+1]);
   end;
   close(input);
   close(output);
end.
posted on 2012-03-29 10:46  淡·雅·墨  阅读(282)  评论(1编辑  收藏  举报