kmp1.2

//继续kan mao pian 
/* 快速右移的实现方法  
  对于现在的已经匹配部分 他是一开始的子串的后缀
  他又是新的匹配部分的前缀
  立即推:他的前缀和后缀要有某种形式
  swj构造了一个集合 N(s,j) = {0 <= t < j | s(0,t) == s(j - t,j)} t是已经匹配部分 j是位置
  只要j>0 N中一定有0 所以不空   再定义Next[0] = -1;
  对每一个s串开始的地方(-1)的位置有一个warden 他与所有串都匹配 
  wcy并不懂 swj解释了一下 就是以上满足前缀一部分就是后缀一部分的全部的t的集合 
  所以if t[i] != s[j] 我们直接从N中取出一个t 让s[t] 对 T[i] 即可~!这就是我们的Next表 
  但t可能有好多 考察位移的长度 我们肯定要取最小的t——位移最大 ——这只有wcy才会这么愚蠢的认为
  我们肯定要取最大的t 这样我们才能保证安全! 
  构造Next 用 递推想法 Next[j] 怎么到 Next[j+1] 
  直观:Next[j+1] <= Next[j] + 1
  iff s[j] = next[j] " = " 成立  前面都相同 这个还相同 而必要性显然
  又替换的时候 j —— Next[j] —— Next[Next[j]] ——........
  所以对于一个序列An = 1+Next^n[j]  n是自然数
  swj不耐烦地说道:“显然An减到0!”因为next[j] < j 
  至于为啥要加1??wcy stupid! warden!
  为啥收敛到0?? stupid! 因为凡是能够递减到0一定无任何匹配的 
  但是我们好像比较难看出复杂度奥
  我怎么知道他后移了多少次? 似乎最坏情形和暴力差不多
  考察算法循环 swj批评wcy“就你这还学数学呢 ”构造watch函数  k = 2*i - j  if then 里面加1 else 里面j减1 k+1 所以k是严格+1 递增
  所以我们可以找supk
  k <= 2(n-1) - (-1) = 2*n-1 
  swj表示自己还可以优化 先看一个栗子
  00010001
  0  0  0  0  1
  -1 0  1  2  3
  比对次数太多了 但是swj想今天看看分析 于是就说下周再说吧 
*/
void buildNext(*s){
    int m = strlen(s), j = 0;
    next[0] = -1,t = next[0];
    while(j < m-1){
        if(t < 0 || s[j] == s[t]){  //匹配的情形 
            next[++j] = ++t; 
        }
        else t = next[t];//wcy第一次看到这条人都傻了 swj讲完之后就比较显然了 
    }

int KMP(char *t,char *s){
    int *next = buildNext(s); //预处理构造next 
    int n = strlen(t),i = 0;  //同暴力1 
    int m = strlen(s),j = 0;
    while(j < m && i < n){
        if(j < 0 || t[i] == s[j]){//KMP.2 j < 0 就是首字符都不匹配的情形  相当于一次成功的匹配 
            i++;j++;
        }
        else{
            j = next[j]; //只需要取出next的所包含的信息就行 不需要退回 
        }
    }
    return i - j;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值