spoj1812 Longest Common Substring II( 后缀自动机 )

 贴个代码...

---------------------------------------------------------------------

#include<cstdio>
#include<cstring>
#include<algorithm>
 
using namespace std;
 
const int maxn = 200009;
const int cn = 26;
 
struct Node {
Node *fa, *ch[cn];
int len, Min, Max;
void upd() {
Min = min(Min, Max);
}
} pool[maxn], *pt, *root, *last;
 
void upd(Node* &t, int &v) {
t->Max = max(t->Max, v);
}
 
Node* newNode(int v) {
pt->fa = NULL;
pt->len = v;
memset(pt->ch, 0, sizeof pt->ch);
return pt++;
}
 
void SAM_init() {
pt = pool;
root = last = newNode(0);
}
 
void Extend(int c) {
Node *p = last, *np = newNode(p->len + 1);
for(; p && !p->ch[c]; p = p->fa)
p->ch[c] = np;
if(!p)
np->fa = root;
else {
Node* q = p->ch[c];
if(p->len + 1 == q->len)
np->fa = q;
else {
Node* nq = newNode(p->len + 1);
memcpy(nq->ch, q->ch, sizeof q->ch);
nq->fa = q->fa;
q->fa = np->fa = nq;
for(; p && p->ch[c] == q; p = p->fa)
p->ch[c] = nq;
}
}
last = np;
}
 
char s[maxn];
 
void SAM_build() {
scanf("%s", s);
for(int i = 0, n = strlen(s); i < n; i++)
Extend(s[i] - 'a');
}
 
bool work() {
if(scanf("%s", s) == -1)
return false;
for(Node* t = root; t != pt; t++)
t->Max = 0;
int n = strlen(s);
Node* t = root;
for(int i = 0, lth = 0; i < n; i++) {
int c = s[i] - 'a';
if(t->ch[c])
upd(t = t->ch[c], ++lth);
else {
for(; t && !t->ch[c]; t = t->fa);
if(!t) 
t = root, lth = 0;
else
lth = t->len + 1, upd(t = t->ch[c], lth);
}
}
for(Node* o = pt; --o != pool; )
upd(o->fa, o->Max);
for(Node* o = pt; --o; ) {
o->upd();
if(o == pool) break;
}
return true;
}
 
int main() {
SAM_init();
SAM_build();
for(Node* t = root; t != pt; t++)
t->Min = t->len;
while(work());
int ans = 0;
for(Node* t = root; t != pt; t++)
ans = max(ans, t->Min);
printf("%d\n", ans);
return 0;
}

--------------------------------------------------------------------- 

 

posted @ 2015-11-17 22:04  JSZX11556  阅读(204)  评论(0编辑  收藏  举报