Description [title]
Byteasar want the walls painted a long character, he was intercepted in order to do it from the front section of characters in a while as a template. The template is then repeated spraying to the appropriate location after got what he wanted the sequence of characters a character can be sprayed several times, but the location can not spray a different character. make a template is a waste of effort, so he wants to template length as small as possible, find the minimum length is. take a sample for ababbababbabababbabababbababbaba , the template for the first 8 characters ababbaba, is the smallest length of the template.
[Input format
input line of no more than \ (500,000 \) a minimum \ (1 \) lowercase characters.
[] Output format
a number represents the minimum length of the template.
There is one that one question I will not do it
I also listened to explanations after struggling for a long time to understand
Pre-knowledge: KMP
first put the string \ (nxt \) array (that is, the KMP) seek out and build out the string \ (fail \) tree
Let me give you an example to help understand this problem
set given string is aabaaba obviously the answer is 4, ie the smallest template for aaba
\ (nxt \) array
\ (fail \) tree (so that each \ (i \) is connected to the \ ([i] NXT \) )
I would not draw
Since the template string must be a prefix of the main string is bound to be a master suffix string so the only possible answer in \ (0 \ sim n \) on this chain (not including 0)
to consider a problem setting the main string is \ (S \) \ (Fail \) a point tree \ (I \) for all points of its sub-tree \ (J \) must satisfy the \ (s [1 \ sim i ] \) is \ ( s [1 \ sim j] \ ) is a suffix (bit around) Why? I do not know to go back and look at \ (nxt \) to define arrays
so we can be understood as equivalent if and only if \ (j \) is \ (i \) when a child node in the tree, we can \ ( s [1 \ sim i] \ ) was sprayed \ (j-i + 1 \ sim j \) a position that is sprayed onto a section to \ (J \) at the end length \ (I \) within the interval
Continue to look below the dividing line -------- ----- appreciated after
Once you understand the rest of the operation is relatively simple to \ (0 \ sim n \) points on the chain marks from all marked \ (0 \) start dfs, each time to a point, traversing all of its son nodes if a son node is marked to indicate that this is the next point in the chain set it to \ (y \) if a son node is not marked then put it subtree (including their own) all points \ (j \ ) a \ (deleted [j] \) is set. 1 \ (deleted [J] =. 1 \) represents \ (s [1 \ sim y ] \) the string can not be sprayed to \ (J \) at the end position on
and then remove it when the way to maintain the current longest period of continuous \ (deleted [j] \) are how long the record is 1 \ (mx \) processed after all the child nodes that hit the mark to the child node continues deep search each reach a hit mark the point \ (x \) immediately determine after if \ (mx <x \) That length \ (x \) template has been sufficient to cover all the vacancies at \ (x \) is a line with the meaning of the questions because the answer to (fail \) \ parent node of the tree must be better than child node numbers so small chain's first \ (x \) is the smallest answer
Annex: sample program implementation
[Code]
#include <iostream>
#include <cstdio>
#include <cstring>
#define ri register int
using namespace std;
char ch[500005];
int n, the_nxt[500005];
int head[500005], pre[1000005], to[1000005], sz;
int pr[500005], nxt[500005];
bool mark[500005];
int mx, ans;
void insert(int u, int v) {
pre[++sz] = head[u]; to[sz] = v; head[u] = sz;
}
void del(int x, int fa) {
pr[nxt[x]] = pr[x]; nxt[pr[x]] = nxt[x];
mx = max(mx, nxt[x] - pr[x] - 1);
for (int i = head[x]; i; i = pre[i]) {
int y = to[i];
if (y == fa) continue;
del(y, x);
}
}
void dfs(int x, int fa) {
if (x > mx) return ans = x, void();
int nnxt;
for (int i = head[x]; i; i = pre[i]) {
int y = to[i];
if (y == fa) continue;
if (!mark[y]) del(y, x);
else nnxt = y;
}
dfs(nnxt, x);
}
int main() {
scanf("%s", ch + 1);
n = strlen(ch + 1);
for (ri i = 2, j = 0; i <= n; i++) {
while (j && ch[j+1] != ch[i]) j = the_nxt[j];
if (ch[j+1] == ch[i]) j++;
the_nxt[i] = j;
}
for (ri i = 1; i <= n; i++) {
insert(i, the_nxt[i]); insert(the_nxt[i], i);
}
for (ri i = n; i > 0; i = the_nxt[i]) mark[i] = 1;
mark[0] = 1;
for (ri i = 1; i <= n; i++) {
pr[i] = i-1; nxt[i] = i+1;
}
dfs(0, 0);
cout << ans << endl;
return 0;
}