**POJ_2774**

In fact, this question is to find the longest common substring. If gets is used to read the string, it will WA, so scanf must be used.

First, we can merge the two strings and add a '$' in the middle to avoid a public prefix in both strings. After processing the height array with the suffix array, scan the height [], if sa [I-1] and sa [I] are both in two strings and the height [I] is greater than max, update max. Finally, output the value of max.

It can be proved that the obtained solution is reasonable. For the suffixes I and j of the merged strings, set I <j. the first character of I is in the first string, and the first character of j is in the second string, assume that the longest common prefix of I and j is k. For each Suffix in Lexicographic Order, whether I is in front of j or j is in front of I, all strings between I and j have at least a public prefix with a length of k, which can be proved by the inverse proof method based on the lexicographic nature. Therefore, k will be found. Since the longest public prefix of any suffix I and j can be found, the obtained solution is reasonable.

#include<stdio.h>

#include<string.h>

#define MAXD 200010

char b[MAXD];

int N, M, r[MAXD], sa[MAXD], rank[MAXD], height[MAXD], wa[MAXD], wb[MAXD], ws[MAXD], wv[MAXD];

void init()

{

int i, j, k;

for(i = 0; b[i]; i ++)

r[i] = b[i];

r[N = i] = '$';

scanf("%s", b);

for(j = 0, ++ i; b[j]; j ++, i ++)

r[i] = b[j];

r[M = i] = 0;

}

int cmp(int *p, int x, int y, int l)

{

return p[x] == p[y] && p[x + l] == p[y + l];

}

void da(int n, int m)

{

int i, j, p, *x = wa, *y = wb, *t;

for(i = 0; i < m; i ++)

ws[i] = 0;

for(i = 0; i < n; i ++)

++ ws[x[i] = r[i]];

for(i = 1; i < m; i ++)

ws[i] += ws[i - 1];

for(i = n - 1; i >= 0; i --)

sa[-- ws[x[i]]] = i;

for(j = 1, p = 1; p < n; j *= 2, m = p)

{

for(p = 0, i = n - j; i < n; i ++)

y[p ++] = i;

for(i = 0; i < n; i ++)

if(sa[i] >= j)

y[p ++] = sa[i] - j;

for(i = 0; i < n; i ++)

wv[i] = x[y[i]];

for(i = 0; i < m; i ++)

ws[i] = 0;

for(i = 0; i < n; i ++)

++ ws[wv[i]];

for(i = 1; i < m; i ++)

ws[i] += ws[i - 1];

for(i = n - 1; i >= 0; i --)

sa[-- ws[wv[i]]] = y[i];

for(t = x, x = y, y = t, x[sa[0]] = 0, p = 1, i = 1; i < n; i ++)

x[sa[i]] = cmp(y, sa[i - 1], sa[i], j) ? p - 1: p ++;

}

}

void calheight(int n)

{

int i, j, k = 0;

for(i = 1; i <= n; i ++)

rank[sa[i]] = i;

for(i = 0; i < n; height[rank[i ++]] = k)

for(k ? -- k : 0, j = sa[rank[i] - 1]; r[i + k] == r[j + k]; k ++);

}

void solve()

{

int i, j, k, ans;

da(M + 1, 128);

calheight(M);

ans = 0;

for(i = 1; i <= M; i ++)

if((sa[i - 1] < N && sa[i] > N) || (sa[i - 1] > N && sa[i] < N))

if(height[i] > ans)

ans = height[i];

printf("%d\n", ans);

}

int main()

{

while(scanf("%s", b) == 1)

{

init();

solve();

}

return 0;

}