Cornelia Street(字符串hash)

题目链接:C. Cornelia Street

题意:给你一个串,这个串是由串A重复n次,串B重复m次,然后串A再重复k次,最后接上一个A的前缀a连接成的,其中n, m, k > 0,0 <= a <= |A|,且串A串B长度相同,让你求最短的串A和串B

Input

输入一个字符串s表示拼接完的字符串(7 <= |S| <= 8e5)
Output

输出长度最短的A,B串

Sample Input

ABABABABZXCVZXCVABABABA

Sample Output

ABAB ZXCV

思路:枚举串的长度,然后字符串hash判断

#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;

typedef long long ll;
typedef unsigned long long ull;

const int N = 1000010;
const int base = 233;

int n;
char s[N];
ull has[N];
ull bpow[N];
int pos1, pos2;

void get_hash() {
    bpow[0] = 1;
    has[0] = 0;
    for(int i = 1; i <= n; i++) {
        bpow[i] = bpow[i - 1] * base;
    }
    for(int i = 1; i <= n; i++) {
        has[i] = has[i - 1] * base + (s[i] - 'a');
    }
}

ull get_val(int l, int r) {
    return has[r] - has[l - 1] * bpow[r - l + 1];
}

int judge(int x) {
    pos1 = pos2 = -1;
    ull vala = -1, valb = -1;
    int flag = 0;
    int i;
    for(i = 1; i <= n; i += x) {
        if(i + x - 1 > n) break;
        ull now = get_val(i, i + x - 1);
        if(flag == 0) {
            vala = now;
            flag = 1;
        } else if(flag == 1) {
            if(now != vala) {
                pos1 = i;
                pos2 = i + x - 1;
                valb = now;
                flag = 2;
            }
        } else if(flag == 2) {
            if(now != valb) {
                if(now == vala) {
                    flag = 3;
                } else {
                    return false;
                }
            }
        } else if(flag == 3) {
            if(now != vala) {
                return false;
            }
        }
    }
    int len = n % x;
    if(len == 0) return true;
    ull last = get_val(i, n);
    ull pre = get_val(1, len);
    if(last != pre) return false;
    return true;
}

int main() {
    scanf("%s", (s + 1));
    n = strlen(s + 1);
    get_hash();
    int flag;
    for(int i = 1; i <= n; i++) {
        if(judge(i)) {
            flag = i;
            break;
        }
    }
    for(int i = 1; i <= flag; i++) {
        printf("%c", s[i]);
    }
    if(pos1 == -1) {
        for(int i = 1; i <= flag; i++) {
            printf("%c", s[i]);
        }
    } else {
        printf(" ");
        for(int i = pos1; i <= pos2; i++) {
            printf("%c", s[i]);
        }
    }
    return 0;
}
View Code
posted @ 2020-11-07 19:19  LightandDust  阅读(155)  评论(0)    收藏  举报