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; }