您的位置:首页 > 其它

[JZOJ 3427] 归途与征程

2016-06-01 12:41 288 查看

Description



对于100%的测试点,1<=N<=100,1<=M<=100000。

Analysis

我们可以把A串视为一些串中间隔着一些星号。

显然,A串头尾都没有星号是有星号的特殊情况。因为无星号可以跳过头尾的串变成头尾都是星号。

下图,上者A,下者B。



我们可以对于A串中的小串与B串做一次KMP,搞一个bz[i][j]表示第i个小串是否能与B的第j个位置往后相应长度匹配。再搞一个f[i][j]表示第j个位置及其右边的第一个能与A串的i小串相匹配的位置。这样一直跳,跳,跳即可。时间复杂度是O(nm)的。

Code

#include<cstdio>
#include<cstring>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,b,a) for(int i=b;i>=a;i--)
using namespace std;
const int N=110,M=200010;
int n,m,len,num,next
,f
[M],c
;
char a
,b[M],s
;
bool p1,pn,bz
[M];
void kmp(int st)
{
int j=0;
fo(i,2,n)
{
while(j && s[i]!=s[j+1]) j=next[j];
next[i]=s[i]==s[j+1]?(++j):(j=0);
}
j=0;
fo(i,2,m*2)
{
while(j && b[i]!=s[j+1]) j=next[j];
if(b[i]==s[j+1]) j++;
if(j==c[st]) bz[st][i-j+1]=1;
}
f[st][m*2+1]=m*2+1;
fd(j,m*2,1)
if(bz[st][j]) f[st][j]=j;
else f[st][j]=f[st][j+1];
}
bool match(int x)
{
int y=x+m-1,l=1,r=num;
if(!p1)
{
if(!bz[l][x]) return 0;
x+=c[l++];
}
if(!pn)
{
if(!bz[r][y-c[r]+1]) return 0;
y-=c[r--];
}
for(;l<=r;l++)
{
x=f[l][x];
if(x>y) return 0;
x+=c[l]-1;
}
if(x>y) return 0;
return 1;
}
int main()
{
scanf("%s\n%s",a+1,b+1);
n=strlen(a+1),m=strlen(b+1);
p1=a[1]=='*',pn=a
=='*';
fo(i,m+1,m*2) b[i]=b[i-m];
int i=0;
while(++i<=n)
{
int len=0;
for(;i<=n && a[i]!='*';i++) s[++len]=a[i];
if(!len) continue;
c[++num]=len;
kmp(num);
}
int ans=0;
fo(i,1,m)
if(match(i)) ans++;
printf("%d",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: