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<=1000000

 

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

next[i] 的含义:从位置1开始的长度为i的字符串的 前缀 和 后缀 的最大匹配长度

例如:

解:

 

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cmath>
 5 #include<cstring>
 6 #include<string>
 7 using namespace std;
 8 inline int read()
 9 {
10     int x=0,w=1;char ch=getchar();
11     while(!isdigit(ch)){if(ch=='-') w=-1;ch=getchar();}
12     while(isdigit(ch)) x=(x<<3)+(x<<1)+(ch-'0'),ch=getchar();
13     return x*w;
14 }
15 const int N=1e6+90;
16 int len1,len2,ne[N];
17 char t[N],s[N];
18 void KMP()
19 {
20    scanf("%s%s",t+1,s+1);
21    len1=strlen(t+1);len2=strlen(s+1);
22    int j;
23    for(int i=2;i<=len2;++i)
24    {
25         j=ne[i-1];
26         while(j&&s[i]!=s[j+1]) j=ne[j];
27         if(s[j+1]==s[i]) ne[i]=j+1; 
28    }
29    j=0;
30    for(int i=1;i<=len1;++i)
31    {
32          while(j&&t[i]!=s[j+1]) j=ne[j];
33          if(t[i]==s[j+1]) j=j+1;
34          if(j==len2) printf("%d\n",i-j+1);
35    }
36    for(int i=1;i<=len2;++i) cout<<ne[i]<<" ";
37 } 
38 int main()
39 {
40     KMP();
41     return 0;
42 }
View Code

 

posted @ 2018-03-13 16:02  月亮茶  阅读(254)  评论(0编辑  收藏  举报