【YBTOJ】【UVA10298】 Power Strings

题目大意:

求一个字符串由多少个重复的子串连接而成。

正文:

我们定义被重复的子串是 \(t\)

如果最长前后缀的长度可以等于 \(n\),那么一段重复的字串,它的最长前后缀,肯定是 \(n\);如果必须小于 \(n\),则它的最长前后缀是 \(n-\text{len}(t)\)

我们可以通过这个性质,先用 KMP 求出最长前后缀,可以算出被重复的子串长度,那么被循环次数就是 \(\frac{n}{n-\text{border}}\),其中 \(\text{border}\) 表示最长前后缀。如果式子不能整除,说明这个字符串没有被重复。

代码:

const int N = 1e6 + 10;

inline ll READ()
{
	ll x = 0, f = 1;
	char c = getchar();
	while (c != '-' && (c < '0' || c > '9')) c = getchar();
	if (c == '-') f = -f, c = getchar();
	while (c >= '0' && c <= '9') x = (x << 3) + (x << 1) + c - '0', c = getchar();
	return x * f;
}

char s[N];
int nxt[N];

void KMP (char *s, int n, int op = 1)
{
	int j = 0;
	for (int i = op; i < n; i++)
	{
		while (j && s[i] != s[j]) j = nxt[j];
		if (s[i] == s[j]) j++;
		if(op) nxt[i + 1] = j;
		else
		{
			if (j == n) {} 
		}
	}
	return;
}

int main()
{
	for (scanf("%s", s); s[0] != '.'; scanf ("%s", s))
	{
		memset (nxt, 0, sizeof nxt);
		int n = strlen(s);
		KMP(s, n);
		if (n % (n - nxt[n])) printf ("1\n");
		else printf ("%d\n", n / (n - nxt[n]));
	}
	return 0;
}
posted @ 2021-05-05 15:46  Jayun  阅读(43)  评论(0编辑  收藏  举报