kmp算法

给定一个模式串S,以及一个模板串P,所有字符串中只包含大小写英文字母以及阿拉伯数字。

模板串P在模式串S中多次作为子串出现。

求出模板串P在模式串S中所有出现的位置的起始下标。

输入格式

第一行输入整数N,表示字符串P的长度。

第二行输入字符串P。

第三行输入整数M,表示字符串S的长度。

第四行输入字符串S。

输出格式

共一行,输出所有出现位置的起始下标(下标从0开始计数),整数之间用空格隔开。

数据范围

1N1041≤N≤104
1M1051≤M≤105

输入样例:

3
aba
5
ababa

输出样例:

0 2


##############################################

 1 #include <iostream>
 2 
 3 using namespace std;
 4 
 5 const int N = 1e4+10, M = 1e5+10;
 6 
 7 char p[N], s[M];
 8 int ne[N];//ne数组,代表从起点到长度为 i 的最长公共前后缀长度
 9 
10 int main(){
11     int n, m;
12     cin >> n >> p + 1 >> m >> s + 1;//下标从 1 开始
13     ne[0] = 0;
14     ne[1] = 0;
15     for(int i = 2;i <= n;++ i){
16         int tmp = i - 1;//找到i的前一个位置
17         do tmp = ne[tmp];//求出从起点到i的前一个位置的最长公共前后缀
18         while(tmp != 0 && p[i] != p[tmp + 1]);//因为最长公共前后缀等于0可能会导致死循环,
19                                             //另外一个判断条件是i位置的数和最长公共前后缀的下一个数不相等
20         if(p[i] == p[tmp + 1])ne[i] = tmp + 1;//下面的if else很巧妙的处理了使上面的循环退出的两种情形
21         else ne[i] = 0;
22     }
23     //i 代表 s , j 代表 pat
24     //用j+1去作比较,一个技巧(记住)
25     for(int i = 1, j = 0;i <= m;++i){
26         if(s[i] == p[j+1]) ++j;
27         else{
28             do j = ne[j];
29             while(j != 0 && p[j + 1] != s[i]);
30             if(p[j + 1] == s[i]) ++j;
31             else j = 0;
32         }
33         if(j == n){
34             cout << i - n<< " ";
35             j = ne[j];
36         }
37     }
38     
39     
40     return 0;
41 }
View Code

end

原文地址:https://www.cnblogs.com/sxq-study/p/12216098.html