zoukankan      html  css  js  c++  java
  • 字符串匹配--(K)MP模板

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

    关于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
    ",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
    ",ans);
    29     }
    30     return 0;
    31 }
  • 相关阅读:
    泰山之行
    泰山之行
    Java EE (2) -- Java EE 6 Enterprise JavaBeans Developer Certified Expert(1z0-895)
    一、浏览器生成消息(2)
    P1194 买礼物 洛谷
    P1195 口袋的天空 洛谷
    P1546||2627 最短网络 Agri-Net 洛谷||codevs
    P3366 最小生成树【模板】 洛谷
    T2627 村村通 codevs
    【目录】我的原创技术视频教程
  • 原文地址:https://www.cnblogs.com/cenariusxz/p/4509794.html
Copyright © 2011-2022 走看看