Description
Solution
注意,这里的匹配是全部都要匹配,不能落下一个字符。
在
A
串中,”* “将字符串分成若干个区间(不包括”*”)。
设
对于每一个区间,都与
B
串做一次
然后我们只需要把 B 串复制一遍,再枚举开头判断就好。
但是这样判断的复杂度达到
考虑优化判断。
于是可以预处理
next[i][j]
表示
bz[i+1][k]=1
大于
j
的
这样复杂度就变成 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;
}