[2016-02-03][KMP算法]

[2016-02-03][KMP算法]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
const int maxn = 1E5 + 10;
const int maxm = 1E4 + 10;
int next[maxm];
int kkk[maxn];
void makenext(char P[]){
         //m p中的元素的数目
         //next[i] 表示 P和P自己匹配,第i个位置,对应的匹配的前缀字符串的末端的位置
         int m = strlen(P);
     memset(next, 0 , sizeof(int)*m);
     for (int i = 1,j = 0;i < m;){
         if (P[i] == P[j]) next[i++] = ++j;
         else  if ( j > 0) j = next[j - 1];
         else  i++;
     }
}
int kmp(char T[],char P[])
{
     //T[] 需要进行匹配的数组
     //P[] 需要完全匹配的数组
     //n T中元素的数目
     //m P中元素的数目
         int n = strlen(T);
         int m = strlen(P);
     makenext(P);
     int i = 0,j = 0; //i表示当前匹配的位置
     for (;i < n;){ //根据需要,可以对条件i < n进行更改,或者直接在循环内加上判断跳出
         if (T[i] == P[j]) kkk[i++] = ++j; //此时的j,表示P和T匹配,第i个位置,对应的匹配的前缀字符串的末端的位置
         else  if ( j > 0 ) j = next[j - 1];
         else  i++;
         }
         //对生成的kkk数组的相关结果进行相关处理和判断
     return  -1;
}

  • KMP算法的应用
    • strstr的优化
      • 1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        27
        28
        29
        30
        const  int  maxm = 1E4 + 10;
        int  next[maxm];
        void  makenext( char  P[]){
                 int  m =  strlen (P);
             memset (next, 0 ,  sizeof ( int )*m);
             for ( int  i = 1,j = 0;i < m;){
                 if (P[i] == P[j]) next[i++] = ++j;
                 else  if ( j > 0) j = next[j - 1];
                 else  i++;
             }
        }
        int  kmp( char  T[], char  P[]){
                 int  n =  strlen (T);
                 int  m =  strlen (P);
             makenext(P);
             for ( int  i = 0,j = 0;i < n;){
                 if (T[i] == P[j]) i++,++j;
                 else  if ( j > 0 ) j = next[j - 1];
                 else  i++;
         
                         if (j == m)       return  i - m;
                 }
             return  -1;
        }
        int  mystrstr( char  str[], char  strsearch[]){
                 //在str中查找strsearch,
                 //      如果找到,返回第一次出现的下标,
                 //      否则返回-1
                return   kmp(str,strsearch);
        }
    • 循环节相关
      • 最后一位 未匹配部分长度如果能整除匹配部分长度,
      • 那么未匹配部分就是循环节(注意是否需要特殊处理,整个字符串是一个循环节的情况)
      • 1
        2
        3
        4
        5
        6
                 int  len =  strlen (str);
                 makenext(str);
                 int  tmp = len - next[len - 1];
                 int  res;
                 if (len % tmp || tmp == len) res = tmp - len % tmp; //不是循环节,补成循环节需要的最少字符
                 else  res = 0; //是循环节
    • 回文字符串相关
      • 最后一个字符,未匹配部分补上去,整个字符串就是回文




来自为知笔记(Wiz)


你可能感兴趣的:([2016-02-03][KMP算法])