Luogu P3375 【模板】KMP字符串匹配

P3375 【模板】KMP字符串匹配

题目描述

如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置。

为了减少骗分的情况,接下来还要输出子串的前缀数组next。如果你不知道这是什么意思也不要问,去百度搜[kmp算法]学习一下就知道了。

输入输出格式

输入格式:

第一行为一个字符串,即为s1(仅包含大写字母)

第二行为一个字符串,即为s2(仅包含大写字母)

输出格式:

若干行,每行包含一个整数,表示s2在s1中出现的位置

接下来1行,包括length(s2)个整数,表示前缀数组next[i]的值。

输入输出样例

输入样例#1:

ABABABC
ABA

输出样例#1:

1
3
0 0 1

说明

时空限制:1000ms,128M

数据规模:

设s1长度为N,s2长度为M

对于30%的数据:N<=15,M<=5

对于70%的数据:N<=10000,M<=100

对于100%的数据:N<=1000000,M<=1000

样例说明:

所以两个匹配位置为1和3,输出1、3

Solution

从matrix67的blog上学习了一下,

设要在A中找B,朴素的匹配方法就是从1 to len(A)每次copy一段len(B)长的和B比较

但是KMP定义了一个next数组

表示对于某个字符串S的前i个字符构成的子串,既是它的后缀又是它的前缀的字符串中(它本身除外),最长的长度记作next[i]

那么我们在朴素匹配失败时可以相当于把模式串往右移动next[i]可以了

具体见KMP算法详解-Matrix67: The Aha Moments

Codes

 1 program wonder;
 2 var
 3     a,b:ansistring;//!!!
 4     i,j,la,lb,tot:longint;
 5     next:array[1..1000] of longint;
 6
 7 procedure iii(i:longint);//找到了
 8 begin
 9     writeln(i-lb+1);
10     j:=next[j];
11 end;
12
13 begin
14     readln(a);
15     readln(b);
16     la:=length(a);
17     lb:=length(b);
18
19     next[1]:=0;
20     j:=0;
21     for i:= 2 to lb do
22       begin
23           while (j>0) and (b[i]<>b[j+1]) do j:=next[j];
24           if b[i]=b[j+1] then j:=j+1;
25           next[i]:=j;
26       end;
27
28    j:=0;
29    for i:= 1 to la do
30      begin
31        while (j>0) and (a[i]<>b[j+1]) do j:=next[j];
32        if a[i]=b[j+1] then inc(j);
33        if j=lb then iii(i);
34      end;
35
36    for i:= 1 to lb do write(next[i],‘ ‘);
37 end.
时间: 2024-12-27 15:32:32

Luogu P3375 【模板】KMP字符串匹配的相关文章

P3375 模板 KMP字符串匹配

P3375 [模板]KMP字符串匹配 来一道模板题,直接上代码. #include <bits/stdc++.h> using namespace std; typedef long long ll; const int N = 1e6 + 5; int n, m; char s1[N], s2[N]; int nxt[N] ; void Get_next(char *s) { int j, L = strlen(s + 1); nxt[1] = j = 0; for(int i = 2; i

洛谷P3375 [模板]KMP字符串匹配

To 洛谷.3375 KMP字符串匹配 题目描述 如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置. 为了减少骗分的情况,接下来还要输出子串的前缀数组next.如果你不知道这是什么意思也不要问,去百度搜[kmp算法]学习一下就知道了. 输入输出格式 输入格式: 第一行为一个字符串,即为s1(仅包含大写字母) 第二行为一个字符串,即为s2(仅包含大写字母) 输出格式: 若干行,每行包含一个整数,表示s2在s1中出现的位置 接下来1行,包括length(s2)个整

算法模板——KMP字符串匹配

功能:输入一个原串,再输入N个待匹配串,在待匹配串中找出全部原串的起始位置 原理:KMP算法,其实这个东西已经包含了AC自动机的思想(fail指针/数组),只不过适用于单模板匹配,不过值得一提的是在单模板大量匹配待匹配串时,这个会有相当大的优势,AC自动机虽然好想一些,但是在这一类问题上的性价比就略低了 1 var 2 i,j,k,l,m,n:longint; 3 a:array[0..100000] of longint; 4 s1,s2:ansistring; 5 begin 6 readl

KMP字符串匹配

1 #include<iostream> 2 3 4 using namespace std; 5 6 #define MAX 255 7 8 typedef unsigned char BYTE; 9 10 typedef BYTE String[MAX+1]; 11 12 bool strAssign(String& strTemp,char* Temp); //定长字符串存储 13 bool strTravel(String& strTemp); //打印 14 void

【luogu P3375 KMP字符串匹配】 模板

题目链接:https://www.luogu.org/problemnew/show/P3375 实际上KMP是一种自己匹配自己的模式.好好理解qaq #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; const int maxn = 1000001; char a[maxn], b[maxn]; int nex

洛谷 P3375 【模板】KMP字符串匹配 || HDU 1686 Oulipo || kmp

HDU-1686 P3375 kmp介绍: http://www.cnblogs.com/SYCstudio/p/7194315.html http://blog.chinaunix.net/uid-8735300-id-2017161.html(mp&kmp) http://www-igm.univ-mlv.fr/~lecroq/string/node8.html(mp&kmp,看上去很正确的例程) http://blog.csdn.net/joylnwang/article/detai

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

题目描述 如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置. 为了减少骗分的情况,接下来还要输出子串的前缀数组next.如果你不知道这是什么意思也不要问,去百度搜[kmp算法]学习一下就知道了. 输入输出格式 输入格式: 第一行为一个字符串,即为s1(仅包含大写字母) 第二行为一个字符串,即为s2(仅包含大写字母) 输出格式: 若干行,每行包含一个整数,表示s2在s1中出现的位置 接下来1行,包括length(s2)个整数,表示前缀数组next[i]的值. 输

P3375 【模板】KMP字符串匹配(全程注释,简单易懂)

题目描述 如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置. 为了减少骗分的情况,接下来还要输出子串的前缀数组next.如果你不知道这是什么意思也不要问,去百度搜[kmp算法]学习一下就知道了. 输入输出格式 输入格式: 第一行为一个字符串,即为s1(仅包含大写字母) 第二行为一个字符串,即为s2(仅包含大写字母) 输出格式: 若干行,每行包含一个整数,表示s2在s1中出现的位置 接下来1行,包括length(s2)个整数,表示前缀数组next[i]的值. 输

P3375 【模板】KMP字符串匹配

题目描述 如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置. 为了减少骗分的情况,接下来还要输出子串的前缀数组next.如果你不知道这是什么意思也不要问,去百度搜[kmp算法]学习一下就知道了. 输入输出格式 输入格式: 第一行为一个字符串,即为s1(仅包含大写字母) 第二行为一个字符串,即为s2(仅包含大写字母) 输出格式: 若干行,每行包含一个整数,表示s2在s1中出现的位置 接下来1行,包括length(s2)个整数,表示前缀数组next[i]的值. 输