拓展kmp模板

来源:互联网 发布:剑网三捏脸数据萝莉 编辑:程序博客网 时间:2024/05/16 10:13
/**********************拓展kmp模板********************************//**next[i]: 以第i位置开始的子串与T的公共前缀长度                                             **//** 也就是next数组满足B[i...i+z-1]==B[0...z-1]的最大的z值(也就是B的自身匹配) *//**ex[i]:以i开始的A的子串与T的公共前缀的长度                                                   **//**也就是ex[i]数组满足B[i...i+z-1]==B[0...z-1]的最大的z值                                 **//*****************************************************************/#include<iostream>#include <cstring>#include <cstdio>using namespace std;const int N = 101010;int next[N],extand[N];void getnext(char *T){     int i,length = strlen(T);     next[0] = length;     //从0开始就是和它自身比较,所以公共前缀是length     for(i = 0;i<length-1 && T[i]==T[i+1]; i++);          next[1] = i;      //从1开始遍历,o(n)的获得next[1];          int a = 1;          //a记录的是当前匹配到的与原串公共前缀最大的起点下标          for(int k = 2; k < length; k++){                  int p = a+next[a]-1, L = next[k-a];                  //p求取的是当前a的最大公共前缀的最后一位                 //L记录的是以k-a开头的与最长公共前缀的长度                 //假设k-a开头的最长公共前缀的长度超过p,那么从k开始就至少有next[k-a]长度的前缀能够与原串匹配                  if( (k-1)+L >= p ){                       int j = (p-k+1)>0? (p-k+1) : 0;                       while(k+j<length && T[k+j]==T[j]) j++;                       next[k] = j, a = k;                  }                  //否则,长度就是next[k-a],不可能有更长的公共前缀                  else next[k] = L;         }}void getextand(char *S,char *T){   memset(next,0,sizeof(next));         getnext(T);//计算出模式串next数组         int Slen = strlen(S), Tlen = strlen(T), a = 0;         int MinLen = Slen>Tlen?Tlen:Slen;         //获取模式串和原串较小的长度         while(a<MinLen && S[a]==T[a]) a++;         extand[0] = a, a = 0;         //获取整个A串从0开始和模式串的匹配程度         for(int k = 1; k < Slen; k++){              int p = a+extand[a]-1, L = next[k-a];              //p是当前取a和模式串匹配最远的位置              //L记录的是以k-a开头的与最长公共前缀的长度              //假设k-a开头的最长公共子串超过p,那么从k开始就至少有extend[k-a]长度的模式串前缀与原串匹配              if( (k-1)+L >= p ){                   int j = (p-k+1)>0? (p-k+1) : 0;                   while(k+j<Slen && j<Tlen && S[k+j]==T[j] ) j++;                   extand[k] = j;a = k;              }              //否则,长度就是next[k-a],不可能有更长的公共前缀              else extand[k] = L;         }}int main(){             char s[N],t[N];             while(~scanf("%s %s",s,t)){                      getextand(s,t);                      for(int i = 0; i < strlen(t); i++)                               printf("%d ",next[i]);                      puts("");                      for(int i = 0; i < strlen(s); i++)                               printf("%d ",extand[i]);                      puts("");             }}/*aaaabaaa aaaa*/

0 0
原创粉丝点击