Cycle (KMP + hash)

  题意:给你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;
    }
more crazy more get!
原文地址:https://www.cnblogs.com/wethura/p/9881354.html