学习字符串处理之KMP算法
来源:互联网 发布:淘宝大学vip课程多少钱 编辑:程序博客网 时间:2024/05/21 08:08
概念一:“前缀包含子串”
前缀包含子串是指,字符串前缀子串中的所有非空非自身子串。
contain_sub_strings = {s|s等于前缀子串 /\s不是前缀子串}(要好好想想理解一下)。
例如:对于字符串”aaaa*a”,其前缀子串”*aaaa“的包含子串的集合就是{“a”, “aa”, “aaa” }(这个例子不是很好,如果您有好的例子,欢迎您提供)。
下面分析字符串匹配的过程,设原串从某一起始地址i开始匹配到了模式串的第m个字符,既是ori[i … i + m] = pat[0 .. m],若此时ori[i + m +1] 与 pat[ m + 1] 不匹配,那么该接下来该怎样处理呢?—————–问题Q
朴素方法的解决方案是,从ori[i+1]开始在ori[i+1 … ]中查找模式串;
这种方法几乎完全没动脑子,是一种极度傻瓜的办法(不可否认,傻瓜的办法总是正确的),下面让我们开始动动脑子:
1)假设pat[0 … m]前缀包含子串的集合 = {“pat[0]”},此时我们很容易就可以知道pat[0]不在pat[1…m]中,那么“问题Q”的答案是什么呢?很简单,从ori[i + m + 1]开始查找模式串,因为ori[i+1 … i + m ] = pat[1 … m] ,也就是说从ori[i + 1]到ori[i + m]为止没有一个字符能与pat[0]匹配;
2)进一步分析,让情况复杂一点,pat[1 … m]中有很多个字符等于pat[0],设这些字符下标的集合等于A0 = {i | pat[i] = pat[0] /\ 1 <= i <= m},记 k = min (A0);
那么这时该怎么回答“问题Q”呢?答案就是从ori[i + k ]开始找模式串, 理由和 1) 一样ori[i+1 .. i +k-1]中没有一个字符能和pat[0]匹配;
3)前缀包含子串集合中的最长子串和最短子串应该选哪一个作为决策的根据?最长子串。
设最长和最短前缀包含子串分别为gs 和 ls,
记A_minlen = {il|pat[il…] = ls /\ 1<=il },
A_maxlen = {ig|pat[ig…] = gs /\1<=ig} ,
k_minlen = min (A_minlen),k_maxlen=min(A_minlen);
分析如下:
和2)一样,我们根据最长子串和最短子串分别可以找到k_maxlen 和k_minlen,k_minlen <= k_maxlen(假设k_minlen > k_manlen,很容易就可以得到最短子串不是最长子串的前缀,根据包含子串的定义这是不可能的),对于任意任意的il,(il
#include<stdio.h>#include<malloc.h>#include<string.h>//求next数组void next_pat(int next[],char parten[],int n){ int i,t,t1; char temch,temch1; int *f= (int*)malloc((n+1)*sizeof(int)); f[0] = next[0]=-1; f[1] = next[1]=0; for(i=2;i<=n;i++) { temch=parten[i-1]; temch1 = parten[i]; t = f[i-1]; while(t>=0 && temch!= parten[t]) { t = f[t]; } t1 = f[i] = t + 1; //优化处理 while(0<=t1 && parten[t1] == temch1) { t1 = f[t1]; } next[i] = t1; } free(f); //printf("%d\n",next[n]);}//统计模式串出现的次数int counter(char *ori,char *par,int *next,int len,int n){ int count=0; int i,j; j=0; i=0; while(i<len) { if(ori[i]==par[j]) { if(j==n-1) { j=next[n]; if(j<0) { j=0; } count++; } else { j++; } i++; } else { j=next[j]; if(j<0) { j=0; i++; } } } return count;}int main(){ int n; char ori[1000005],par[10005]; int next[10005];// FILE *in = NULL;// in = fopen("input.txt","r");// fscanf(in,"%d",&n); scanf("%d",&n); int i; int re; int len; for(i=0;i<n;i++) {// fscanf(in,"%s",par);// fscanf(in,"%s",ori); scanf("%s%s",par,ori); len=strlen(par); next_pat(next,par,len); re=counter(ori,par,next,(int)strlen(ori),len); printf("%d\n",re); }// fclose(in); return 0;}
- 学习字符串处理之KMP算法
- 字符串 之 KMP算法
- 字符串之KMP算法
- 字符串之KMP算法
- 字符串处理基础算法-KMP
- 字符串算法之kmp算法
- 字符串算法之KMP算法
- 字符串匹配算法之KMP算法的学习
- 吾之简单的KMP算法学习,字符串操作基本功
- 字符串匹配之KMP算法
- 字符串匹配算法之KMP
- 字符串匹配之KMP算法
- 字符串匹配之KMP算法
- 字符串匹配之KMP算法
- 字符串匹配之KMP算法
- 字符串匹配之KMP算法
- 字符串匹配 之 KMP算法
- 字符串匹配之KMP算法
- 网络的那些事之IP
- 关于DevOps你必须知道的11件事
- 项目中jar包没有引错,但是方法undefined问题
- Json序列化和反序列化
- ACID、Data Replication、CAP与BASE
- 学习字符串处理之KMP算法
- KDE图形界面语言设置
- 服务器端和客户端有什么区别
- Java 正则表达式的总结和一些小例子(验证和修改过的版本)
- 递归思维:之类斐波那契数列
- ROS Navigation-----发布Odometry信息
- 分治法-----归并排序(C语言描述)
- Python的下载与安装
- echarts集成 实例-包含柱状图、悬浮提示、文本提示