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