zoukankan      html  css  js  c++  java
  • 扩展kmp入门+比赛模板

    https://wenku.baidu.com/view/8e9ebefb0242a8956bece4b3.html 参考了这个ppt 理解起来还是有点费劲的(还是推荐一下这个课件 里面概念和思路给的比较全)

    关键点 在extend[1...k]都已经求出来的情况下,求extend[k]。

    关键利用s中有一部分和t相等。extend[k+1]的长度<=(s和t相等部分长度时候) extend[k+1]=next[k-a+1];

    否者超出的部分要一一匹配并更新,a,p;

    上个板子:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <string>
    #include <algorithm>
    #define mt(a) memset(a,0,sizeof(a))
    using namespace std;
    typedef long long ll;
    const ll mod=1e9+7;
    ll extend[1000001];
    ll Next[1000001];
    ll min(ll x,ll y)
    {
        if(x>y) return y;
        return x;
    }
    void getNext(string t)
    {
        mt(Next);
        ll len=t.length();
        Next[0]=len;
        ll a,p;
        a=1;
        while( a<len && t[a]==t[a-1]) a++; // 求出长度为1的时候 解为多少 
        Next[1]=a-1;
        a=1;
        for(ll i=2;i<len;i++) // 后续的按照算法来就好
        {
            p=a+Next[a]-1;
            if((i-1)+Next[i-a] < p ) Next[i]=Next[i-a];// 第一种情况 没有超过等于的部分
            else // 超过的话就不好直接用next的定义 需要后续的遍历
            {
                ll j = (p - i + 1) > 0 ? (p - i + 1) : 0;
                while(i + j < len && t[i+j] == t[j]) j++;
                Next[i]=j;
                a=i;
            }
        }
    }
    void exkmp(string s,string t) // s->extend  t->next
    {
        getNext(t);
        ll a,p;//
        ll slen=s.length();
        ll tlen=t.length();
        a=p=0;
        ll len=min(s.length(),t.length());
        while(p<len && t[p]==s[p]) p++; // after
        extend[0]=p;
        for(ll i=1;i<slen;i++)
        {
            p=a+extend[a]-1; // update
            if( (i-1)+Next[i-a] < p) extend[i]=Next[i-a];
            else
            {
                ll j = (p - i + 1) > 0 ? (p - i + 1) : 0;
                while( j < tlen && i+j < slen && s[i + j] == t[j]) j++;
                extend[i]=j;
                a=i;
            }
        }
    }
    // 核心 一个起始位置a  一个最远匹配位置p 然后Next 和 extend数组
    int main()
    {
        string s,t;// s->exkmp t->Next
        int Case;
        scanf("%d",&Case);
        while(Case--)
        {
            cin>>s>>t;
            exkmp(s,t);
           
        }
        return 0;
    }
  • 相关阅读:
    oracle数据库版本进化的关键节点
    到底什么是数据库呢?
    迁移数据之后,读取数据库变得很慢
    为什么越来越多的人使用python呢?
    20135306 2.4 ELF文件格式分析
    20135306 2.3程序破解实践
    20135306黄韧模块实践报告
    Linux内核学习总结
    Linux内核分析期中知识点总结
    LINUX内核分析第八周学习总结——进程的切换和系统的一般执行过程
  • 原文地址:https://www.cnblogs.com/z1141000271/p/7404717.html
Copyright © 2011-2022 走看看