[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...

【JZOJ 3427】归途与征程

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

[JZOJ3395]【NOIP2013模拟】Freda的传呼机

Description 为了 随时 与 rainbow快速交流, Freda制造了 两部传呼机 。Freda和 rainbow所在的地方有N座房屋、M条双向 光缆 。每条光缆连接两座房屋, 传呼机...

JZOJ 3506. 【NOIP2013模拟11.4A组】善良的精灵

Description从前有一个善良的精灵。一天,一个年轻人B找到她并请他预言他的未来。这个精灵透过他的水晶球看到这个年轻人将要遇见一个非常美丽的公主并要娶她。。精灵在一张纸上画了N个点并用一些线段将...

JZOJ3453. 【NOIP2013中秋节模拟】连通块(connect)

题目Description你应该知道无向图的连通块的数量,你应该知道如何求连通块的数量。当你兴奋与你的成就时,破坏王Alice拆掉了图中的边。当她发现,每删去一条边,你都会记下边的编号,同时告诉她当前...

jzoj3518【NOIP2013模拟11.6A组】进化序列

3518. 【NOIP2013模拟11.6A组】进化序列DescriptionAbathur采集了一系列Primal Zerg 的基因样本,这些基因构成了一个完整的进化链。为了方便,我们用A0,A1…...

JZOJ 3453【NOIP2013中秋节模拟】连通块

原题Description你应该知道无向图的连通块的数量,你应该知道如何求连通块的数量。当你兴奋与你的成就时,破坏王Alice拆掉了图中的边。当她发现,每删去一条边,你都会记下边的编号,同时告诉她当前...

JZOJ 3498【NOIP2013模拟联考14】图形变换

题目大意:给你N个点的坐标。现有一些操作,求执行完所有操作后这些点的坐标。 操作1:让这些点的坐标加上一些数; 操作2:让这些点的坐标乘上一些数; 操作3:让这些点绕着一个中心点顺时针旋转θ角度...

JZOJ-senior-3502. 【NOIP2013模拟11.4B组】方格游戏

3502. 【NOIP2013模拟11.4B组】方格游戏(game) (Standard IO)Time Limits: 1000 ms Memory Limits: 131072 KB Deta...

JZOJ 3428 【NOIP2013模拟】刺杀大使

原题Description伊朗伊斯兰革命卫队(某恐怖组织)正在策划一起刺杀行动,他们的目标是沙特驻美大使朱拜尔。他们来到了沙特驻美使馆,准备完成此次刺杀,要进入使馆首先必须通过使馆前的防御迷阵。迷阵一...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:[JZOJ3427]【NOIP2013模拟】归途与征程
举报原因:
原因补充:

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