zoukankan      html  css  js  c++  java
  • kmp优化

    https://www.nowcoder.com/acm/contest/147/F

    即做4个kmp,可持久化每增加一个字符后的match。

    题外话:假如说在a串中找b串,做kmp的过程其实在不断的使b串的前缀与当前匹配到的串的后缀对齐,扫a串,每增加一个字符就更新一次match(最大匹配位置),当match为b串长度-1时,即找到了b串,更新操作均摊下来为O(1)。注意b串为ccccccccccc的情况,匹配失败,每次只会往前跳一个字符,在本题中就会成为卡时间的地方,优化加一行代码即可,见代码。

    #include <cstdio>
    #include <cstring>
    #include <cctype>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <stack>
    #include <set>
    using namespace std;
    typedef long long ll;
     
    int kmp_fail[4][100005];
    char kmp_p[4][100005];
    void getFail(char *P, int *fail) {
        int match = -1;
        fail[0] = -1;
        for (int i = 1; P[i]; ++i) {
            while (match >= 0 && P[match + 1] != P[i]) {              match = fail[match];
            }
            if (P[match + 1] == P[i]) {              match++;
            }
            fail[i] = match;  
            if(match!=-1&&P[i+1]==P[match+1]) fail[i] = fail[match];
            //优化:两者相等,那么i+1失配时,match+1也会失配,则可跳过 
        }
    }
    char s[100005];
    int main()
    {
        int n;
        scanf("%d",&n);
        for(int i=0;i<n;i++)
        {
            scanf("%s",kmp_p[i]);
            getFail(kmp_p[i], kmp_fail[i]);
        }
        vector<int>vt[5];
        scanf("%s",s);
        int match[4]={-1,-1,-1,-1};
        int len[4];
        int mm=100000000;
        for(int i=0;i<n;i++) {len[i]=strlen(kmp_p[i]);mm=min(mm,len[i]);}
        printf("%d
    ",mm);
        for(int i=0;s[i];i++)
        {   int mi=100000000;
            if(s[i]=='-')
            {
                for(int j=0;j<n;j++)
                {   if(vt[j].size()>0)
                    {vt[j].pop_back();
                     if(vt[j].size()>0) match[j]=vt[j][vt[j].size()-1];
                        else match[j]=-1;
                      
                     
                    }
                }
                if(vt[4].size()>0)
                {
                vt[4].pop_back();
                if(vt[4].size()>0) printf("%d
    ",vt[4][vt[4].size()-1]);
                        else printf("%d
    ",mm);
                }
                else printf("%d
    ",mm);
            }
            else {
                for(int j=0;j<n;j++)
                {
                    while(match[j]>=0&&kmp_p[j][match[j]+1]!=s[i])
                            match[j]=kmp_fail[j][match[j]];
                    if(kmp_p[j][match[j]+1]==s[i]) match[j]++;
                    mi=min(mi,len[j]-match[j]-1);
                    vt[j].push_back(match[j]);
                
                }
                vt[4].push_back(mi);
                printf("%d
    ",mi);
                }
        }
         
        return 0;
    }
  • 相关阅读:
    cidaemon.exe过程cpu入住率和关闭cidaemon.exe加工方法
    .net 一些常用的工具来破解
    关于加密和解密的设计思路
    oncopy和onpaste
    来迁移数据管道
    使用JSP实现商场购物车模块
    2014在辛星Javascript口译科
    Lua学习 1) —— Android呼叫变量值和分配
    HttpSQS
    手机后端开发
  • 原文地址:https://www.cnblogs.com/lnu161403214/p/9580978.html
Copyright © 2011-2022 走看看