洛谷 P3375 模板 KMP字串匹配

2021-07-31 13:19:08 字數 1362 閱讀 1370

題目大意:

給出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...