我們想如果匹配到第二個串的i的位置,第一個串可以匹配到哪,也就是說我們需要知道a[s]..a[.s+i-1]等於b[1]..b[i]的所有的s,可以用bitset存,然後就就枚舉i用後綴數組判斷一下就行。
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <bitset>
#include <time.h>
using namespace std;
const int MAXN=20005;
int t1[MAXN],t2[MAXN],c[MAXN];//求SA數組需要的中間變量,不需要賦值
//待排序的字符串放在s數組中,從s[0]到s[n-1],長度爲n,且最大值小於m,
//除s[n-1]外的所有s[i]都大於0,r[n-1]=0
//函數結束以後結果放在sa數組中
bool cmp(int *r,int a,int b,int l)
{
return r[a] == r[b] && r[a+l] == r[b+l];
}
void da(int str[],int sa[],int rank[],int height[],int n,int m)
{
n++;
int i, j, p, *x = t1, *y = t2;
//第一輪基數排序,如果s的最大值很大,可改爲快速排序
for(i = 0;i < m;i++)c[i] = 0;
for(i = 0;i < n;i++)c[x[i] = str[i]]++;
for(i = 1;i < m;i++)c[i] += c[i-1];
for(i = n-1;i >= 0;i--)sa[--c[x[i]]] = i;
for(j = 1;j <= n; j <<= 1)
{
p = 0;
//直接利用sa數組排序第二關鍵字
for(i = n-j; i < n; i++)y[p++] = i;//後面的j個數第二關鍵字爲空的最小
for(i = 0; i < n; i++)if(sa[i] >= j)y[p++] = sa[i] - j;
//這樣數組y保存的就是按照第二關鍵字排序的結果
//基數排序第一關鍵字
for(i = 0; i < m; i++)c[i] = 0;
for(i = 0; i < n; i++)c[x[y[i]]]++;
for(i = 1; i < m;i++)c[i] += c[i-1];
for(i = n-1; i >= 0;i--)sa[--c[x[y[i]]]] = y[i];
//根據sa和x數組計算新的x數組
swap(x,y);
p = 1; x[sa[0]] = 0;
for(i = 1;i < n;i++)
x[sa[i]] = cmp(y,sa[i-1],sa[i],j)?p-1:p++;
if(p >= n)break;
m = p;//下次基數排序的最大值
}
int k = 0;
n--;
for(i = 0;i <= n;i++)rank[sa[i]] = i;
for(i = 0;i < n;i++)
{
if(k)k--;
j = sa[rank[i]-1];
while(str[i+k] == str[j+k])k++;
height[rank[i]] = k;
}
}
int Rank[MAXN],height[MAXN];
int RMQ[MAXN];
int mm[MAXN];
int best[15][MAXN];
int r[MAXN];
int sa[MAXN];
void initRMQ(int n)
{
mm[0]=-1;
for(int i=1;i<=n;i++)
mm[i]=((i&(i-1))==0)?mm[i-1]+1:mm[i-1];
for(int i=1;i<=n;i++)best[0][i]=i;
for(int i=1;i<=mm[n];i++)
for(int j=1;j+(1<<i)-1<=n;j++)
{
int a=best[i-1][j];
int b=best[i-1][j+(1<<(i-1))];
if(RMQ[a]<RMQ[b])best[i][j]=a;
else best[i][j]=b;
}
}
int askRMQ(int a,int b)
{
int t;
t=mm[b-a+1];
b-=(1<<t)-1;
a=best[t][a];b=best[t][b];
return RMQ[a]<RMQ[b]?a:b;
}
int lcp(int a,int b)
{
if(a>b)swap(a,b);
return height[askRMQ(a+1,b)];
}
bitset<MAXN/2>a[MAXN/2],in[MAXN/2],ans,nn;
void init(){
in[0].reset();
in[0][0]=1;
for(int i=1;i<MAXN/2;i++){
in[i]=in[i-1];
in[i].set(i);
}
}
char x[MAXN];
char y[MAXN];
pair<int,int>p1[MAXN/2];
int main()
{
int n;
init();
while(scanf("%s",x)!=EOF){
scanf("%s",y);
n=strlen(x);
for(int i=0;i<n;i++){
r[i]=x[i];
}
r[n]=126;
for(int i=n+1;i<=2*n;i++){
r[i]=y[i-n-1];
}
r[2*n+1]=0;
da(r,sa,Rank,height,2*n+1,128);
for(int i = 1;i <=2*n+1;i++)
RMQ[i] = height[i];
initRMQ(2*n+1);
for(int i=0;i<n;i++){
int w=lcp(Rank[i],Rank[n+1]);
p1[i].first=-w;
p1[i].second=i;
}
sort(p1,p1+n);
int no=0;
nn.reset();
for(int i=n;i>=1;i--){
while(no<n&&-p1[no].first>=i){
nn.set(p1[no].second);
no++;
}
a[i]=nn;
}
ans.reset();
for(int i=1;i<=n;i++){
if(i==n){
ans|=(a[i]<<n);
continue;
}
int w=lcp(Rank[n+i+1],Rank[0]);
ans|=((a[i]<<i)&(in[i+w]^in[i-1]));
}
for(int i=1;i<=n;i++){
if(ans.test(i)) printf("1");
else printf("0");
}
printf("\n");
}
}