Description
Input
第一行为字符串A。
第二行为字符串B。
Output
输出在B的所有循环同构串中,有多少个能够与A匹配。
Sample Input
输入1:
aaaa
aaaa
输入2:
a*a
aaaaaa
输入3:
abc
abacabadabacaba
Sample Output
输出1:
4
输出2:
6
输出3:
15
Data Constraint
对于30%的数据,M<=20;
对于80%的测试点,M<=200;
对于100%的测试点,1<=N<=100,1<=M<=100000。
.
.
.
.
.
.
.
分析
将B串倍长,将A串按通配符分割,分割后预处理每段在B串的匹配位置,枚举起始位置,强制要求A串首尾与起始、终止位置匹配,中间的段贪心取最左的
.
.
.
.
.
.
程序:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int n,m,t,f[200010][60],next[200010][60],a[110],b[200010],q[110],p[110],l[110],ans=0;
char ch[100010];
void kmp(int num,int x)
{
p[1]=0;
int j=0;
for (int i=2;i<=x;i++)
{
while (j>0&&q[j+1]!=q[i]) j=p[j];
if (q[j+1]==q[i]) j++;
p[i]=j;
}
j=0;
for (int i=1;i<=2*m-1;i++)
{
while (j>0&&q[j+1]!=b[i]) j=p[j];
if (q[j+1]==b[i]) j++;
if (j==x)
{
f[i-x+1][num]=1;
j=p[j];
}
}
}
void find()
{
t=0;
int i=1;
while (i<=n)
{
while (a[i]<0 && i<=n) i++;
if (i>n) break;
t++;
l[t]=0;
while (a[i]>=0&&i<=n)
{
l[t]++;
q[l[t]]=a[i];
i++;
}
kmp(t,l[t]);
}
for (int j=1;j<=t;j++)
{
next[2*m][j]=m+m;
for (int i=2*m-1;i>=1;i--)
if (f[i][j]==1) next[i][j]=i; else next[i][j]=next[i+1][j];
}
}
int main()
{
scanf("%s",ch);
n=strlen(ch);
for (int i=1;i<=n;i++)
a[i]=ch[i-1]-'a';
scanf("%s",ch);
m=strlen(ch);
for (int i=1;i<=m;i++)
b[i]=ch[i-1]-'a';
for (int i=m+1;i<=2*m-1;i++)
b[i]=b[i-m];
for (int i=0;i<=25;i++)
f[2*m][i]=2*m;
memset(f,0,sizeof(f));
find();
for (int i=1;i<=m;i++)
{
int ed=i+m-1,x;
x=next[i][1];
if (x+l[1]-1>ed) continue;
if (a[1]>=0&&x!=i) continue;
for (int j=2;j<=t;j++)
x=next[x+l[j-1]][j];
if (x+l[t]-1>ed||x==0) continue;
if (a[n]>=0&&f[ed-l[t]+1][t]!=1) continue;
ans++;
}
printf("%d",ans);
return 0;
}