洛谷 P3375 【模板】KMP字符串匹配

来源:互联网 发布:软件 qa qc 编辑:程序博客网 时间:2024/06/06 09:03

题目大意:
给出N长的字符串S1,M长的字符串S2,求出s2在s1中所有出现的位置。用KMP做,先输入每一次S2出现的位置,然后输出S2的前缀数组next。

题解:
KMP:
next[i]表示需要匹配的字串的最长公共前后缀的长度。
怎么求next[i]呢?
首先初值next[1]=0,j=0
对于每一个如果s2[j+1]=s2[i],没有疑问,j=j+1
不过如果s2[j+1]不等于s2[i],我们要匹配到j=0或者s2[j+1]=s2[i]的时候才能退出,不然就j=next[j],因为next[j]即代表前j个的最长公共前后缀总长,也代表前缀的位置。
然后怎么找S1中的S2呢?
j=0
如果s1[i]=s2[j+1],毫无疑问是累加下去的。
如果s1[i]<>s2[j+1],我们就要设法让它满足s1[i]=s2[j+1],同上,我们要匹配到j=0(匹配失败)或者s2[j+1]=s1[i]的时候才能退出。
如果j=length(s2),就代表已经在S1中找到了S2,这时候,就输出位置i-length(s2)+1,然后因为在i位置完全找到的,这时候i的前 “next[j] ” 个(包括i)绝对是等于s2的前next[j]个的,这时候从j=next[j]来继续枚举。

var    next:array [0..1001] of longint;    n,m,i,j:longint;    s,t:ansistring;begin      readln(s);      readln(t);      next[1]:=0;      j:=0;      for i:=2 to length(t) do          begin               while (j>0) and (t[j+1]<>t[i]) do j:=next[j];               if t[j+1]=t[i] then inc(j);               next[i]:=j;          end;      j:=0;      for i:=1 to length(s) do      begin            while (j>0) and (t[j+1]<>s[i]) do j:=next[j];            if s[i]=t[j+1] then inc(j);            if j=length(t) then               begin                    writeln(i-j+1);                    j:=next[j];               end;      end;      for i:=1 to length(t) do write(next[i],' ');end.
1 0
原创粉丝点击