題目大意:
給出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.
洛谷 P3375 模板 KMP字串匹配
如題,給出兩個字串s1和s2,其中s2為s1的子串,求出s2在s1中所有出現的位置。為了減少騙分的情況,接下來還要輸出子串的字首陣列next。輸入格式 第一行為乙個字串,即為s1 第二行為乙個字串,即為s2 輸出格式 若干行,每行包含乙個整數,表示s2在s1中出現的位置 接下來1行,包括length...
洛谷P3375 模板 KMP字串匹配
如題,給出兩個字串s1和s2,其中s2為s1的子串,求出s2在s1中所有出現的位置。為了減少騙分的情況,接下來還要輸出子串的字首陣列next。輸入格式 第一行為乙個字串,即為s1 僅包含大寫字母 第二行為乙個字串,即為s2 僅包含大寫字母 輸出格式 若干行,每行包含乙個整數,表示s2在s1 現的位置...
洛谷 P3375 模板 KMP字元匹配
如題,給出兩個字串s1和s2,其中s2為s1的子串,求出s2在s1中所有出現的位置。為了減少騙分的情況,接下來還要輸出子串的字首陣列next。輸入格式 第一行為乙個字串,即為s1 第二行為乙個字串,即為s2 輸出格式 若干行,每行包含乙個整數,表示s2在s1中出現的位置 接下來1行,包括length...