首先还是要回到卷积的定义上
C(k)=Σi+j=kai∗bj
这题这种做法我是看了题解之后才知道的。
如果a是 a1a2a3a4 ,B是 b1b2b3 ,如果我们做卷积,那么其中 C5=a2∗b3+a3∗b2+a4∗b1 ,这和我们的比较方法相反,所以如果我们把B反过来,那么就能利用卷积完成这个比较。
要利用这个性质,分两步计算。
1. a结尾若是1,b结尾若是0,则ax,bx即做FFT的对应位置权值是1,这样求出的是a为1,b为0的矛盾位数。
2. a结尾若是0,b结尾若是1,则ax,bx即做FFT的对应位置权值是1,这样求出的是a为0,b为1的矛盾位数。
因此这两步做完就能判断矛盾的位数。
最后还要做一个KMP来判断前面七位是否满足。
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std;
const int MAXN = 524288+1000;
const int INF = 0x3f3f3f3f;
const double eps = 1e-8;
const double pi = acos(-1.0);
struct cp
{
double x,y;
cp() {}
cp(double x,double y):x(x),y(y) {}
inline double real()
{
return x;
}
inline cp operator * (const cp& r) const
{
return cp(x*r.x-y*r.y, x*r.y+y*r.x);
}
inline cp operator - (const cp& r) const
{
return cp(x-r.x,y-r.y);
}
inline cp operator + (const cp& r) const
{
return cp(x+r.x,y+r.y);
}
};
cp a[MAXN],b[MAXN];
int r[MAXN],res[MAXN],ax[MAXN],bx[MAXN],n,m;
int s1[MAXN],s2[MAXN];
void fft_init(int nm,int k)
{
for (int i=0; i<nm; i++) r[i]= (r[i>>1]>>1) | ((i&1) << (k-1));
}
void fft(cp ax[],int nm,int op)
{
for (int i=0; i<nm; i++) if (i<r[i]) swap(ax[i],ax[r[i]]);
for (int h=2,m=1; h<=nm; h<<=1,m<<=1)
{
cp wn = cp(cos(op*2*pi/h),sin(op*2*pi/h));
for (int i=0; i<nm; i+=h)
{
cp w(1,0);
for (int j=i; j<i+m; j++,w=w*wn)
{
cp t=w*ax[j+m];
ax[j+m] = ax[j]-t;
ax[j] = ax[j]+t;
}
}
}
if (op==-1) for (int i=0; i<nm; i++) ax[i].x /= nm;
}
void trans(int n,int m,int x,int y)
{
int nm=1,k=0;
while (nm < 2*n || nm <2*m ) nm<<=1,++k;
for (int i=0; i<n; i++)
{
if ((s1[i]&1) == x)
ax[i] = 1;
else
ax[i] = 0;
}
for (int i=0; i<m; i++)
{
if ((s2[m-i-1]&1) == y)
bx[i] = 1;
else
bx[i] = 0;
}
for (int i=0; i<n; i++) a[i] = cp(ax[i],0);
for (int i=0; i<m; i++) b[i] = cp(bx[i],0);
for (int i=n; i<nm; i++) a[i] = cp(0,0);
for (int i=m; i<nm; i++) b[i] = cp(0,0);
fft_init(nm,k);
fft(a,nm,1);
fft(b,nm,1);
for (int i=0; i<nm; i++) a[i] = a[i] * b[i];
fft(a,nm,-1);
nm = n+m-1;
for (int i=0; i<nm; i++) res[i] += (int)(a[i].real() + 0.5);
}
int nex[MAXN];
void getnext(int m)
{
int j=0;
for (int i=1;i<m;i++)
{
while (j && s2[i]!=s2[j]) j=nex[j];
if (s2[i]==s2[j]) j++;
nex[i+1]=j;
}
}
void KMP_Count(int n,int m)
{
int ans=INF,pos=0;
for (int i=0,j=0;i<n;i++)
{
while(j && s1[i]!=s2[j]) j=nex[j];
if (s1[i] == s2[j])
{
j++;
if(j==m)
{
if (ans > res[i])
{
ans = res[i];
pos = i-m+1;
}
j=nex[j];
}
}
else j=nex[j];
}
if (ans == INF)
printf("No\n");
else
{
printf("Yes\n");
printf("%d %d\n",ans,pos+1);
}
}
int main()
{
while (scanf("%d%d",&n,&m)!=EOF)
{
memset(res,0,sizeof res);
for (int i=0; i<n; i++) scanf("%d",&s1[i]);
for (int i=0; i<m; i++) scanf("%d",&s2[i]);
trans(n,m,1,0);
trans(n,m,0,1);
for (int i=0;i<n;i++) s1[i]/=10;
for (int i=0;i<m;i++) s2[i]/=10;
getnext(m);
KMP_Count(n,m);
}
return 0;
}