单模式字符串匹配算法KMP
KMP算法:
2 int KMP(char* s, FILE *file, int*pos) /**/
3 {
4 int i =0;
5 fseek(file, *pos, SEEK_SET); /* 定位文件读位置 */
6 char c = fgetc(file);
7 while(s[i] !='\0'&& c != EOF){
8 if(s[i] == c){ /* 如果当前字符与c匹配,下标指向下一个字符,同时获得下一个c */
9 c = fgetc(file);
10 ++i;
11 } else /* 否则,下标指向当前字符的前一个匹配项 */
12 i = next[i];
13 if(i ==-1){ /* 如果下标被赋值为-1, 从说明c之前的子串与s不符,c从新获得,下标从0开始比较 */
14 c = fgetc(file);
15 i =0;
16 }
17 }
18 if(s[i] =='\0'){ /* 如果下标移动到最后,则匹配成功,记录文件当前位置,同时返回匹配位置 */
19 *pos = ftell(file);
20 return*pos - strlen(s);
21 }else /* 否则返回-1 */
22 return-1;
23 }
获得模式串的next数组算法:(算法中c1代表文件中正在与s进行匹配的字符)
next[i]值的含义要求一下两个条件:
条件①:存在j,满足max{0<=j<=i且s[0]~s[j]=s[i-j]~s[i]};
条件②:在满足条件①情况下,若s[i+1]!=s[j+1],则next[i+1]=j;若s[i+1]=s[j+1],则next[i+1]=next[j+1];
2 {
3 next[0] =-1; /* next[0]=-1固定值 */
4 int i =0, j =-1;
5 while(s[i] !='\0'){ /* 开始求next[i]值,直到s末尾 */
6 /* 此时,next[i]已经得出 */
7 if(j ==-1|| s[i] == s[j] ){ /* 然后利用循环寻找满足条件①的j,直到j满足条件①或j=-1停止 */
8 /* 此时有两种情况,①0<=j<=i且s[0]~s[j]=s[i-j]~s[i];②j=-1;可以统一用以下语句处理 */
9 ++i;++j; /* 针对以上两种情况,i和j下标都加1,以便求得下一个next[i]的值 */
10 if(s[i] != s[j]) /* ①若在s[0]~s[j-1]=s[i-j-1]~s[i-1]的情况下,有s[i]!=s[j],显然next[i]=j;
11 ②若在j=0的情况下,有s[i]!=s[0],则与s[i]不匹配外来的字符c,仍有可能与s[j]匹配,故next[i]=0 */
12 next[i] = j;
13 else /* ①若s[0]~s[j-1]=s[i-j-1]~s[i-1]的情况下,有s[i]=s[j],由条件①知j是max{...}的,
14 所以与s[i]不匹配的外来字符c1和与s[j]不匹配的外来字符c2,会被回退到同一个匹配下标,故next[i]=next[j]
15 ②若j=0,有s[i]=s[0],则同上情况的解释,next[i]=next[0]=-1 */
16 next[i] = next[j]
17 }else /* 对应3行if语句不成立情况, */
18 j = next[j];
19 }
20 }
^_^