大白书型模板,并没有写成函数形式:

 

关于p数组(失配指针数组)的含义: - 数组下标从0开始

p[i]表示当发现待匹配串(s)已匹配位置与模板串(t)的t[i]不匹配时,t中最近一个可以尝试继续匹配的位置。即当已经完成了s串与t[0]~t[i-1]的匹配时,发现s串后一个字符与t[i]不匹配,此时s串到当前不构成匹配的位置前可以视为与 t[0] ~ t[ p[i]-1 ] 完成了匹配,因此可以继续匹配s串当前字符与 t[ p[i] ] 。此时如果仍然不匹配可以继续对 t 当前不匹配的位置做失配转跳,直至转跳到t中的当前匹配位置为0位置。

因此实际上p[i]也具有这样的性质:t[0]~t[ p[i]-1 ] 是 t[0]~t[i-1] 的所有前缀中的最长可匹配后缀。

 

 

此外,对于一个长度为 m 的串自匹配,在此模板中 m-p[m] 就是这个串的最小循环节长度(最后一个循环可以不完整) - 数组下标从0开始

 

另一个关于自匹配后的失配指针的性质:对于该串的所有可以作为循环节的长度是:m-p[m] , m-p[p[m]] , m-p[p[p[m]]]……直到 p[x] = 0。 - 数组下标从0开始

 

 

这个是下标从0开始的:

 

 

 1 #include <stdio.h>
 2 #include <string.h>
 3 typedef long long ll;
 4 #define MP make_pair
 5 #define PB push_back
 6 const int mod = 1e9 + 7;
 7 const double eps = 1e-8;
 8 const int INF = 0x3f3f3f3f;
 9 const int maxn = 1e6 + 5;
10 const int maxm = 1e5 + 5;
11 
12 char s[maxn],t[maxm];    //s为待匹配串,t为模板串
13 int p[maxn];    //自匹配数组
14 
15 int main(){
16     int T;
17     scanf("%d",&T);
18     while(T--){
19         scanf("%s%s", t, s);    //这个是字符串从下标0开始的
20         int i,j = 0,ans=0;    // j = 0 注意, ans记录字符串出现次数
21         int n = strlen(s), m = strlen(t);    //在题目中遇到过,其实strlen很慢,所以如果不先存起来可能有TLE的风险
22         p[0] = p[1] = 0;    //初始化自匹配数组
23         for(i = 1 ; i < m ; ++ i){    //自匹配
24             while(j && t[i] != t[j])j = p[j];
25             if(t[i] == t[j])++ j; 
26             p[i+1] = j;
27         }
28         j = 0;            //注意 j=0
29         for(i = 0 ; i < n ; ++ i){    //串匹配
30             while(j && s[i] != t[j])j = p[j];
31             if(s[i] == t[j])++ j;
32             if(j == m){
33                 ans++;        //此处记录出现次数(模板串在待匹配串中可重叠),或改为直接break表示是否出现过
34             }
35         }
36         printf("%d\n",ans);
37     }
38     return 0;
39 }

 

 

 

 

数组下标从1开始:

 1 #include<stdio.h>
 2 #include<string.h>
 3 
 4 const int maxn=1e6+5;
 5 const int maxm=1e4+5;
 6 
 7 char s[maxn],t[maxm];
 8 int p[maxm];
 9 
10 int main(){
11     while(scanf("%s%s",s+1,t+1)!=EOF){   // 。。这个是从下标1开始的,恩修改的还是比较多的所以不是很建议
12         int i,j,ans=0;
13         int n=strlen(s+1),m=strlen(t+1);
14         p[1]=p[2]=1;
15         for(i=2;i<=m;i++){
16             j=p[i];
17             while(j>1&&t[i]!=t[j])j=p[j];
18             p[i+1]=t[i]==t[j]?j+1:1;
19         }
20         j=1;
21         for(i=1;i<=n;i++){
22             while(j>1&&s[i]!=t[j])j=p[j];
23             if(s[i]==t[j])j++;
24             if(j==m+1){
25                 ans++;
26             }
27         }
28         printf("%d\n",ans);
29     }
30     return 0;
31 }