解题报告 tyvj 1068

题意略。

这道题让我一度有了撞墙的冲动。。。。。。

Y 的一个水水更健康的扩展 kmp , WA 了四次。。。。。

额,大概是这么做:

  首先,kmp 是神马,不会的自觉去看 matrix67 blog。

  然后,我们可以发现,主程序的时候,通常输出匹配位置时,是在:

    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 print;

  这意味着什么?bingo,这个 j 就是当前两个字符串所匹配的字符数---------------说白了,就是这个题的答案。。。。

  额,不过有一点要注意,就是,如果在 m 位置可以匹配 j 个字符,那么显然在 m 位置也可以匹配 p[j] 个字符,所以要计算一下累和。关于这一点,题解上说的是“根据KMP自我匹配数组的性质,如果以A串某个元素结尾有一个长度为11的字串可以与B串匹配的话,以该元素结尾的长度为kmp[11] = 4的字串也是可以匹配的。所以说cnt[4] += cnt[11]。”但是呢,本蒟蒻没有看懂。。。。。于是本蒟蒻发现这个用的方法很简单,拍数据!!!!

  其实,好多好神奇的规律,在考场一般也只能观察出来,TAT。。。。。所以,数学帝是非常值得膜拜的。。。。

 

代码 SueMiller:

program ACRush;
var a,b:ansistring;
n,m,kk,i,j,k:longint;
p,q:array[0..200001]of longint;

procedure gp;
var j:longint;
begin
p[1]:=0;
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;

begin
readln(n,m,kk);
readln(a);
readln(b);
gp;

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);                             //这一行和上一行,全写的是 b[i]  b[j+1]  。。。。。贡献 2 WA 。
inc(q[j]);
if j=m then j:=p[j];
end;

for i:=m downto 1 do
inc(q[p[i]],q[i]);          //没观察到这个规律,1 WA 。
for i:=1 to kk do
begin
readln(k);
writeln(q[k]-q[k+1]);   //没观察到这个规律,1 WA 。------>根据我们的计算方法可以得出,当一个字符及其之前的字符一共可以匹配 k+1 次时,那么他一定也能匹配 k 次。。。。。偶们求的是累和嘛。。。。
end;
end.

posted @ 2012-03-22 11:04  木小漾  阅读(245)  评论(0编辑  收藏  举报