Sza-Template 「POI 2005」

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

Guess you like

Origin www.cnblogs.com/ak-dream/p/AK_DREAM20.html