官方题解不是很详细
首先有一个结论:若A=pa+sa B=pb+sb
A、B串循环同构,则可以构造一个可行方案(pa,sb) (sa,pb)中有一个是最长匹配,这个不难用反证法证明。
对于s1,s2串,我们穷举s1的每一个后缀i,设s1[i..i+len-1]=s2[0..len-1] len是最长匹配
那么不难得到,如果存在k使得k<=len且s1[0..i-1]=s2[k..k+i-1]
那么,两串前缀s1[0..i+k-1]为循环同构
因此我们预处理w[i][j]表示s1[0..i]=s2[j..j+i]是否相等,w数组我们可用bitset压位存储
求出这个数组我们只需要建立后缀数组然后顺着height[]找即可
下面我们在将变量代换,前缀p=i+k-1循环同构的条件为i-1<=p<=len+i-1且w[i-1][p]为1
这个条件我们在压位的情况下可以用位运算处理
问题得解
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 3 using namespace std; 4 bitset<10000> w[10010],ans,pre[10010],tmp; 5 char s2[20010],s1[20010]; 6 int d[20],lg[20010],h[20010],s[20010],rk[20010],sa[20010],x[20010],y[20010],a[20010]; 7 int f[20010][16],n; 8 pair<int,int> q[20010]; 9 bool cmp(int a,int b,int j) 10 { 11 if (y[a]==y[b]) 12 { 13 if (a+j<=n&&b+j<=n) return y[a+j]!=y[b+j]; 14 else if (a+j>n&&b+j>n) return 0; 15 else return 1; 16 } 17 return y[a]!=y[b]; 18 } 19 20 void suffix() 21 { 22 int m=28; 23 memset(s,0,sizeof(s)); 24 for (int i=1; i<=n; i++) s[a[i]]++; 25 for (int i=1; i<=m; i++) s[i]+=s[i-1]; 26 for (int i=n; i; i--) sa[s[a[i]]--]=i; 27 int p=1; rk[sa[1]]=1; 28 for (int i=2; i<=n; i++) 29 { 30 if (a[sa[i]]!=a[sa[i-1]]) ++p; 31 rk[sa[i]]=p; 32 } 33 int j=1; m=p; 34 while (m<n) 35 { 36 memcpy(y,rk,sizeof(rk)); 37 memset(s,0,sizeof(s)); 38 p=0; 39 for (int i=n-j+1; i<=n; i++) x[++p]=i; 40 for (int i=1; i<=n; i++) 41 if (sa[i]>j) x[++p]=sa[i]-j; 42 for (int i=1; i<=n; i++) s[rk[i]=y[x[i]]]++; 43 for (int i=1; i<=m; i++) s[i]+=s[i-1]; 44 for (int i=n; i; i--) sa[s[rk[i]]--]=x[i]; 45 rk[sa[1]]=1; p=1; 46 for (int i=2; i<=n; i++) 47 { 48 if (cmp(sa[i],sa[i-1],j)) ++p; 49 rk[sa[i]]=p; 50 } 51 m=p; j<<=1; 52 } 53 p=0; h[1]=0; 54 for (int i=1; i<=n; i++) 55 { 56 if (rk[i]==1) continue; 57 int j=sa[rk[i]-1]; 58 while (i+p<=n&&j+p<=n&&a[i+p]==a[j+p]) ++p; 59 h[rk[i]]=p; 60 if (p) p--; 61 } 62 } 63 64 int ask(int x,int y) 65 { 66 int k=lg[y-x+1]; 67 return min(f[x][k],f[y-d[k]+1][k]); 68 } 69 70 void rmq() 71 { 72 for (int i=1; i<=n; i++) 73 f[i][0]=h[i]; 74 for (int j=1; j<=lg[n]; j++) 75 { 76 for (int i=1; i<=n; i++) 77 if (i+d[j]-1<=n) f[i][j]=min(f[i][j-1],f[i+d[j-1]][j-1]); 78 else break; 79 } 80 } 81 82 int main() 83 { 84 // freopen("1002.in","r",stdin); 85 d[0]=1; lg[1]=0; 86 for (int i=1; i<=15; i++) 87 { 88 d[i]=d[i-1]*2; 89 for (int j=d[i-1]; j<=min(20005,d[i]-1); j++) lg[j]=i-1; 90 } 91 pre[0][0]=1; 92 for (int i=1; i<10000; i++) 93 { 94 pre[i]=pre[i-1]; 95 pre[i][i]=1; 96 } 97 while (scanf("%s%s",s1,s2)!=EOF) 98 { 99 int l=strlen(s1); 100 n=0; 101 for (int i=0; i<l; i++) a[++n]=s1[i]-'a'+1; 102 a[++n]=27; 103 for (int i=0; i<l; i++) a[++n]=s2[i]-'a'+1; 104 a[n+1]=0; 105 suffix(); rmq(); 106 for (int i=0; i<l; i++) w[i].reset(); 107 int len=n,m=0; 108 for (int i=rk[1]+1; i<=n; i++) 109 { 110 len=min(len,h[i]); 111 if (!len) break; 112 else if (sa[i]>l+1) q[++m]=make_pair(len-1,sa[i]-l-2); 113 } 114 len=h[rk[1]]; 115 for (int i=rk[1]-1; i; i--) 116 { 117 if (!len) break; 118 else if (sa[i]>l+1) q[++m]=make_pair(len-1,sa[i]-l-2); 119 len=min(len,h[i]); 120 } 121 sort(q+1,q+1+m); 122 tmp.reset(); int j=m; 123 for (int i=l-1; i>=0; i--) 124 { 125 while (j&&q[j].first==i) tmp[q[j--].second]=1; 126 w[i]=tmp; 127 } 128 ans.reset(); 129 for (int i=0; i<l; i++) 130 { 131 int x=rk[i+1],y=rk[l+2]; 132 if (x>y) swap(x,y); 133 len=ask(x+1,y); 134 if (len) 135 { 136 if (i) ans|=(pre[i-1]^pre[i+len-1])&(w[i-1]<<(i-1)); 137 else ans|=pre[len-1]; 138 } 139 } 140 for (int i=0; i<l; i++) 141 if (ans[i]) printf("1"); else printf("0"); 142 puts(""); 143 } 144 }