SPOJ 1811. Longest Common Substring (LCS,兩個字串的最長公共子串, 字尾自動機SAM)
阿新 • • 發佈:2019-02-06
/* *********************************************** Author :kuangbin Created Time :2013-9-8 23:27:46 File Name :F:\2013ACM練習\專題學習\字尾自動機\new\SPOJ_LCS.cpp ************************************************ */ #include <stdio.h> #include <string.h> #include <iostream> #include <algorithm> #include <vector> #include <queue> #include <set> #include <map> #include <string> #include <math.h> #include <stdlib.h> #include <time.h> using namespace std; const int CHAR = 26; const int MAXN = 250010; struct SAM_Node { SAM_Node *fa, *next[CHAR]; int len; int id, pos; SAM_Node(){} SAM_Node(int _len) { fa = 0; len = _len; memset(next,0,sizeof(next)); } }; SAM_Node SAM_node[MAXN*2], *SAM_root, *SAM_last; int SAM_size; SAM_Node *newSAM_Node(int len) { SAM_node[SAM_size] = SAM_Node(len); SAM_node[SAM_size].id = SAM_size; return &SAM_node[SAM_size++]; } SAM_Node *newSAM_Node(SAM_Node *p) { SAM_node[SAM_size] = *p; SAM_node[SAM_size].id = SAM_size; return &SAM_node[SAM_size++]; } void SAM_init() { SAM_size = 0; SAM_root = SAM_last = newSAM_Node(0); SAM_node[0].pos = 0; } void SAM_add(int x,int len) { SAM_Node *p = SAM_last, *np = newSAM_Node(p->len + 1); np->pos = len; SAM_last = np; for(; p && !p->next[x];p = p->fa) p->next[x] = np; if(!p) { np->fa = SAM_root; return; } SAM_Node *q = p->next[x]; if(q->len == p->len + 1) { np->fa = q; return; } SAM_Node *nq = newSAM_Node(q); nq->len = p->len + 1; q->fa = nq; np->fa = nq; for(; p && p->next[x] == q; p = p->fa) p->next[x] = nq; } void SAM_build(char *s) { SAM_init(); int len = strlen(s); for(int i = 0;i < len;i++) SAM_add(s[i] - 'a', i+1); } char str1[MAXN], str2[MAXN]; int main() { //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); while(scanf("%s%s",str1,str2) == 2) { SAM_build(str1); int len = strlen(str2); SAM_Node *tmp = SAM_root; int ans = 0; int t = 0; for(int i = 0;i < len;i++) { if(tmp->next[str2[i]-'a']) { tmp = tmp->next[str2[i]-'a']; t++; } else { while(tmp && !tmp->next[str2[i]-'a']) tmp = tmp->fa; if(tmp == NULL) { tmp = SAM_root; t = 0; } else { t = tmp->len + 1; tmp = tmp->next[str2[i]-'a']; } } ans = max(ans,t); } printf("%d\n",ans); } return 0; }