ACPC2015Day3 F / AOJ 2763 - Miko Mi String

問題はこちら

入力文字列Sについて、長さをn、最小周期をpとします。
さらに、q=p*floor(n/(3*p)+1)とおきます。
このようにすると、
2*q<nであるときかつそのときに限り、題意を満たす文字列A,Bが存在し、さらに求めるべきABの長さはqとなる
ということが容易に証明できます。

以上の考察を基にコードを書くと次のようになります。

#include <stdio.h>
#include <string.h>

char s[1000010];
int mp[1000010];

int main(){
	int i, n, t, p, q = 0;

	fgets(s, sizeof(s), stdin);
	n = strlen(s) - 1;

	mp[0] = -1;
	t = -1;
	for(i = 0; i < n; ++i){
		while(t >= 0 && s[t] != s[i]){
			t = mp[t];
		}
		mp[i + 1] = ++t;
	}
	
	p = n - mp[n];
	q = p * (n / (3 * p) + 1);
	if(q * 2 >= n){
		q = 0;
	}

	if(q != 0){
		printf("Love %.*s!\n", q, s);
	}
	else{
		puts("mitomerarenaiWA");
	}

	return 0;
}

さらに頑張ると、次の162バイトのコードになります。

char s[1<<20];m[1<<20],n,t;main(){for(gets(s);s[n];m[++n]=--t)for(;t&&s[~t]-s[n];t=m[~t]);t-=~n;n=!printf(t*2<n?"Love %.*s!\n":"mitomerarenaiWA\n",t*=n/3/t+1,s);}