Repeat substring
Topic link: ybt efficient advanced 2-3-2
Topic
Given several strings, ask each string at most how many identical substrings are repeatedly concatenated.
Ideas
For this question, we consider using KMP, first run KMP on this string.
那 f a i l n fail_n failnIt means 1 ∼ failn 1\sim fail_n1∼failnSubstring of n − failn + 1 ∼ n n-fail_n+1\sim nn−failn+1∼The substrings of n are equal.
Then we consider under what circumstances will it consist of multiple identical substrings.
Let's draw a picture to see:
this is a number, not a string, we just have to assume the positions of equal substrings.
If you want to become two paragraphs, it must be separated from the middle. (As shown in the figure below)
If you want to divide it into three sections, you have to divide it three times, but you can only separate from one place.
When we consider where to separate, it is equivalent to third-class separation.
Then we need s 1 ∼ 4 = s 5 ∼ 8 = s 9 ∼ 12 s_{1\sim4}=s_{5\sim8}=s_{9\sim12}s1∼4=s5∼8=s9∼12.
Then think about the two parts divided into 1 ∼ a 1\sim a1∼a sumn − a + 1 ~ n n-a + 1 \ sim nn−a+1∼n , that is less than or equal toaaa positive integerbbb , there will be1 ∼ b 1\sim b1∼b sumn − a + 1 ~ n − a + b n-a + 1 \ sim n-a + bn−a+1∼n−a+b is equal.
In fact, if there is another one greater than or equal tobbb , less than or equal toaaa positive integerccc , there will beb ∼ cb\sim cb∼c 和 n − a + b ∼ n − a + c n-a+b\sim n-a+c n−a+b∼n−a+c。
Then we can find that we let the length be 8 88 is fine!
There are four that intersect, and then the first four and the last four of the two that are separated are equal, which is exactly what we want.
What if it is divided into four sections?
It’s not hard to think that the length is 9 99。
To summarize the law, when the sequence length is nnn , you have to divide it intoxxx 段时, f a i l n fail_n failnIt should be n − nx n-\dfrac{n}{x}n−xn.
(Of course, nnn must bexxThe multiple of x , otherwise it will be indistinguishable)
Let's take a look when failn fail_nfailnWhen it has been determined, it should be divided into several sections.
That is nn − failn \dfrac{n}{n-fail_n}n−failnn, The shift item is available.
Of course, you can also know, the premise is nnn 是 n − f a i l n n-fail_n n−failnMultiples of, otherwise it can only be divided into one. (Just one whole)
Code
#include<cstdio>
#include<cstring>
using namespace std;
int an, ans, fail[1000001], j;
char a[1000001];
int main() {
scanf("%s", a + 1);
an = strlen(a + 1);
while (an != 1 || a[1] != '.') {
//KMP
j = 0;
for (int i = 2; i <= an; i++) {
while (j && a[i] != a[j + 1]) j = fail[j];
if (a[i] == a[j + 1]) j++;
fail[i] = j;
}
if (an % (an - fail[an]) == 0) printf("%d\n", an / (an - fail[an]));//可以分段
else printf("1\n");//分不了段,就只能一整个
scanf("%s", a + 1);
an = strlen(a + 1);
}
return 0;
}