SPOJ 1812 Longest Common Substring II(后缀自动机)(LCS2)

时间:2023-03-09 00:03:45
SPOJ 1812 Longest Common Substring II(后缀自动机)(LCS2)

A string is finite sequence of characters over a non-empty finite set Σ.

In this problem, Σ is the set of lowercase letters.

Substring, also called factor, is a consecutive sequence of characters occurrences at least once in a string.

Now your task is a bit harder, for some given strings, find the length of the longest common substring of them.

Here common substring means a substring of two or more strings.

Input

The input contains at most 10 lines, each line consists of no more than 100000 lowercase letters, representing a string.

Output

The length of the longest common substring. If such string doesn't exist, print "0" instead.

题目大意:求多个字符串的最长公共子串。

思路:据说把多个串拼起来会MLE还是TLE?SPOJ太慢了……

给第一个串建立后缀自动机,然后把每个点的ans置为当前后缀的LCS,dp为当前某个串能匹配的最长后缀

然后每次弄完用每个点的dp更新ans……图是一个DAG……

哎呀好难说看代码吧……

代码(1500MS):

 #include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std; const int MAXN = + ;
char buf[MAXN];
struct State {
State *fail, *go[];
int val, dp, ans;/*
State() :
fail(0), val(0) {
memset(go, 0, sizeof go);
}*/
}*root, *last;
State statePool[MAXN * ], *cur; void init() {
//memset(statePool, 0, 2 * strlen(buf) * sizeof(State));
cur = statePool;
root = last = cur++;
} void extend(int w) {
State *p = last, *np = cur++;
np->ans = np->val = p->val + ;
while (p && !p->go[w])
p->go[w] = np, p = p->fail;
if (!p) np->fail = root;
else {
State*q = p->go[w];
if (p->val + == q->val) np->fail = q;
else {
State *nq = cur++;
memcpy(nq->go, q->go, sizeof q->go);
nq->ans = nq->val = p->val + ;
nq->fail = q->fail;
q->fail = nq;
np->fail = nq;
while (p && p->go[w] == q)
p->go[w] = nq, p = p->fail;
}
}
last = np;
} inline void update_max(int &a, const int &b) {
if(a < b) a = b;
} inline void update_min(int &a, const int &b) {
if(a > b) a = b;
} struct Node {
State *p;
bool operator < (const Node &rhs) const {
return p->val < rhs.p->val;
}
} a[MAXN * ]; int main() {
init();
scanf("%s", buf);
for(char *pt = buf; *pt; ++pt)
extend(*pt - 'a');
int m = ;
for(State *p = statePool; p != cur; ++p) {
a[m++].p = p;
}
sort(a, a + m);
int n = ;
while(scanf("%s", buf) != EOF) {
++n;
State *t = root;
int l = ;
for(char *pt = buf; *pt; ++pt) {
int w = *pt - 'a';
if(t->go[w]) {
t = t->go[w];
update_max(t->dp, ++l);
}
else {
while(t && !t->go[w]) t = t->fail;
if(!t) l = , t = root;
else {
l = t->val;
t = t->go[w];
update_max(t->dp, ++l);
}
}
}
for(int i = m - ; i > ; --i) {
State *p = a[i].p;
update_min(p->ans, p->dp);
update_max(p->fail->dp, min(p->dp, max(p->fail->val, p->dp)));
p->dp = ;
}
}
int ans = ;
for(int i = m - ; i >= ; --i) update_max(ans, a[i].p->ans);
printf("%d\n", ans);
}