题意:给你2个串,让你判断2个字符串的前缀是否满足首尾连接形成的环是不是一样的。
思路:我们需要提前知道的是满足条件的前缀一定满足 strA = str1 + str2, strB = str2 + str1。然后我们先求出其中的一个的KMP,然后去匹配,那么我们匹配过程中一定会有一个公共长度j,那么我们利用好j这一段再加上判断剩下的部分是不是相等的就好了,那么这一段就可以相当于str2,然后我们再用带有顺序的hash技术,将其他的映射出来就好了,然后用的时候直接乘上当前值的进制值就好了,就是有一个需要移一下位才能进行同等级的比较。
#include<bits/stdc++.h> using namespace std; const int maxn = 1e4 + 7; const int base = 233; long long p[maxn], hass[2][maxn]; int n, nex[maxn]; char A[maxn], B[maxn]; bool ans[maxn]; long long getVal(int t, int l, int r){ return hass[t][r] - hass[t][l - 1] * p[r - l + 1]; } bool check(int t, int a, int b){ if(a == b) return true; return getVal(t, a + 1, b) == getVal(t^1, 1, b - a); } void kmp(int al, char a[], int bl, char b[], int t){ int i, j; for(nex[1] = j = 0, i = 2; i <= al; nex[i ++] = j){ while(j && a[j + 1] != a[i]) j = nex[j]; if(a[j + 1] == a[i]) j ++; } for(j = 0, i = 1; i <= bl; i ++){ while(j && a[j + 1] != b[i]) j = nex[j]; if(a[j + 1] == b[i]){ j ++; if(!ans[i]) ans[i] = check(t, j, i); } if(j == al) j = nex[j]; } } int main(){ //freopen("data", "r", stdin); for(int i = p[0] = 1; i < maxn; i ++) p[i] = p[i - 1] * base; while(~scanf(" %s %s", A + 1, B + 1)){ int len = strlen(A + 1); for(int i = 1; i <= len; i ++){ ans[i] = false; hass[0][i] = hass[0][i - 1] * base + A[i]; hass[1][i] = hass[1][i - 1] * base + B[i]; } kmp(len, A, len, B, 0); kmp(len, B, len, A, 1); for(int i = 1; i <= len; i++ ) printf("%c", "01"[ans[i]]);printf(" "); } return 0; }