[JZOJ3427]【NOIP2013模拟】归途与征程

原创 2016年06月01日 12:47:29

Description

这里写图片描述

Solution

注意,这里的匹配是全部都要匹配,不能落下一个字符。

A串中,”* “将字符串分成若干个区间(不包括”*”)。
bz[i][j]表示A串中第i个区间和B串中第j位开头能否匹配
对于每一个区间,都与B串做一次KMP,可以在O(NM)的时间范围内求出bz

然后我们只需要把B串复制一遍,再枚举开头判断就好。

但是这样判断的复杂度达到O(M),总的是O(M2)

考虑优化判断。

于是可以预处理next[i][j]表示bz[i+1][k]=1大于jk最小值

这样复杂度就变成O(NM)

Code

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cmath>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fod(i,a,b) for(i=a;i>=b;i--)
using namespace std;
int n,m,m1,num,a[101],next[101][200001];
char s1[101],s2[200001];
bool bz[101][200001];
void kmp(int ar,int lt,int rt)
{
    if (rt<lt)
    {
        int i;
        fo(i,0,m1+1) bz[ar][i]=1;
        return; 
    }
    int len=rt-lt+1,i,i1,j=0,j1=0,p[101];
    p[1]=0;
    fo(i1,2,len)
    {
        i=i1+lt-1;
        j1=j+lt-1;
        while (j>0&&s1[j1+1]!=s1[i]) 
        {
            j=p[j];
            j1=j+lt-1;
        }
        if (s1[j1+1]==s1[i]) j++;
        j1=j+lt-1;
        p[i1]=j;
    }
    j=0;
    fo(i,1,m1)
    {
        j1=j+lt-1;
        while (j>0&&s1[j1+1]!=s2[i]) 
        {
            j=p[j];
            j1=j+lt-1;
        }
        if (s1[j1+1]==s2[i]) j++;
        j1=j+lt-1;
        if (j==len) bz[ar][i-j+1]=1;
    }
}
bool pd(int st)
{
    int i=st,j=1;
    if (bz[j][st]==0) return 0; 
    a[0]=0;
    while (i!=0&&i+a[j]-a[j-1]-2<=st+m-1) 
    {
        if (j==num-1&&bz[num][st+m-a[num]+a[num-1]+1]) return 1;
        i=next[j][i+a[j]-a[j-1]-2];
        j++;
    }
    return 0; 
}
int main()
{
    scanf("%s",s1+1);
    scanf("\n");
    scanf("%s",s2+1);
    n=strlen(s1+1);
    m=strlen(s2+1);
    num=0;
    int i,j;
    fo(i,1,m-1) s2[i+m]=s2[i]; 
    m1=2*m-1;
    fo(i,1,n) if (s1[i]=='*') a[++num]=i;
    a[++num]=n+1;
    memset(bz,0,sizeof(bz));
    fo(i,1,num)
    {
        kmp(i,a[i-1]+1,a[i]-1); 
    } 
    fod(i,m1-1,0)
    {
        fo(j,0,num-1)
        {
            next[j][i]=bz[j+1][i+1]?i+1:next[j][i+1];
        }
    }
    int ans=0;
    fo(i,1,m) 
    {
        if (i==2)
        {
            n++;
            n--;
        }
        if(pd(i)) ans++;
    }
    cout<<ans;
} 
版权声明:本文为博主原创文章,未经博主允许不得转载。 举报

相关文章推荐

【NOIP2013模拟】归途与征程

Description给出两个字符串,A和B,|A|=n,|B|=m,并且A中有许多*——通配符。这个东西可以匹配任意的字符串,包括空串。现在问你,B的循环同构的字符串中,有多少个可以和A匹配? n...

[2012-2013ACM-ICPC,NEERC,Western Subregional Contest]Pattern Matching/[JZOJ3427]归途与征程

题目大意SS是一个非空字符串,包含小写拉丁字母以及特殊字符∗*。TT是另一个非空字符串,只包含小写拉丁字母。 定义SS能匹配TT当且仅当:除了SS中的∗*能匹配TT中任意多个字符(包括空串)以外,其...

精选:深入理解 Docker 内部原理及网络配置

网络绝对是任何系统的核心,对于容器而言也是如此。Docker 作为目前最火的轻量级容器技术,有很多令人称道的功能,如 Docker 的镜像管理。然而,Docker的网络一直以来都比较薄弱,所以我们有必要深入了解Docker的网络知识,以满足更高的网络需求。

[JZOJ 3427] 归途与征程

Description 对于100%的测试点,1<=N<=100,1<=M<=100000。Analysis我们可以把A串视为一些串中间隔着一些星号。 显然,A串头尾都没有星号是有星号的特殊情况。因...

【JZOJ 3427】归途与征程

Solution 题意简化以后就是:在b串的同构中,有多少个可以按顺序匹配多个串。 我们可以先把a串拆开,每个做一遍KMP的预处理, 倍长b串,枚举b串的开头,依次匹配过去, 每次匹配的时候,记录一下...

【NOIP2013模拟】绿豆蛙的归宿

Description随着新版百度空间的上线,Blog宠物绿豆蛙完成了它的使命,去寻找它新的归宿。 给出一个有向无环图,起点为1终点为N,每条边都有一个长度,并且从起点出发能够到达所有的点,所有的点...

【NOIP2013模拟】Heaven Cow与God Bull

Description给定一个整数n,求一个整数m,满足m<=n,并且m/phi(m)的值最大。 注:phi(m)代表m的欧拉函数,即不大于m且与m互质的数的个数。Solution方法要求 MAX...

【NOIP2013模拟】KC的陶器

『NOIP2013模拟』KC的陶器【NOIP2013模拟】KC的瓷器 (Standard IO) Time Limits: 1000 ms Memory Limits: 262144 KB De...

NOIP2013模拟最小比例

题目图中共有N个点的完全图,每条边都有权值,每个点也有权值。要求选出M个点和M-1条边,构成一棵树,使得:所有边的权值与所有点的权值之和的比率最小。样例输入:第一行包含两个整数N和M(2<=N<=15...

【NOIP2013模拟】粉刷匠

Description给出n个球,其中有C1个球是颜色1的,有C2个球是颜色2的,有C3个球是颜色3的…… 有Ck个球是颜色k的。求相邻两个球颜色不同的排列方案。 k<=15,ci<=6,数据组数...

【NOIP2013模拟】DY引擎

Description给出一张无向图,问从1到n的最短路。 你可以瞬移k次,每次从u瞬移到v的条件是:u到v中存在一条不经过收费站的距离<=L的路径。当然,u或v可以是收费站。 收费站不会直接告诉...
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)