zoukankan      html  css  js  c++  java
  • 剪花布条

    https://loj.ac/problem/10043

    题目描述

      给出两个字符串(A)(B),求(A)最多同时分成几个互不重叠的(B)

    思路

      单字符串的匹配问题,可以考虑用(KMP)解决,属于模板题。

      首先来介绍一下(KMP)(KMP)是单字符串的匹配算法,即只有一个母串和一个匹配串。在进行匹配时,如果暴力枚举,时间复杂度最坏为(O(nm)),而(KMP)可以实现((n))的时间复杂度。我们考虑对于字符串(A)的某一位置进行匹配时,暴力我们需要(B)的每一位置进行配对,而实际上这里有很多状态是多余的,所以(KMP)的核心就是构造(P)数组。对于匹配串(B),我们用(k=P[ j ])表示(B[ 1...k ] =B[ j - k + 1...j ]),或者说最长公共前后缀。而对于这个(P)数组,当(A)字符串的(i)位置与(B)字符串(j)位置匹配时,我们考虑下一位(i+1)(j+1),如果匹配就继续,否则(j)就转到(P[ j ])继续匹配,因为显然这样对于匹配串(B [ 1...P[ j ] ])仍然是匹配的,即(B [ 1...P[ j ] ] = A [ i - P[ j ] +1...i ])

      现在我们就要想如何求出(P)数组。首先我们假设(P[ 1 ],P [ 2 ] ... P [ i ]),考虑求出(P[ i + 1 ])。我们可以用类似的方法,把(B)串既看作母串又看作匹配串,如果当前匹配就增加(j),否则就将(j)不断往(P[ j ])移动,因为之前的(P)数组都已求出。

      这道题唯一要注意的是互不重叠的串,所以匹配完后(j)要清零。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    char s[1100],s1[1100];
    int pre[1100];
    int main() 
    {
        while(~scanf(" %s",s+1))
        {
            if(strlen(s+1)==1&&s[1]=='#')break ; 
            scanf(" %s",s1+1);
            pre[1]=0;
            int n=strlen(s+1),m=strlen(s1+1);
            int j=0;
            for(int i=1;i<m;i++)
            {
                while(j>0&&s1[i+1]!=s1[j+1])j=pre[j];
                if(s1[i+1]==s1[j+1])j++;
                pre[i+1]=j;
            }
            int ans=0;j=0;
            for(int i=0;i<n;i++)
            {
                while(j>0&&s[i+1]!=s1[j+1])j=pre[j];
                if(s[i+1]==s1[j+1])j++;
                if(j==m)
                {
                    ans++;
                    j=0;
                }
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
    
  • 相关阅读:
    shell流程控制
    shell编程变量介绍与表达式详解
    shell编程简介
    反向代理与负载均衡
    存储库之mongodb,redis,mysql
    请求库之requests,selenium
    解析库之re、beautifulsoup、pyquery
    爬虫基本原理
    Django 函数和方法的区别
    Django 知识补漏单例模式
  • 原文地址:https://www.cnblogs.com/fangbozhen/p/11788152.html
Copyright © 2011-2022 走看看