SPOJ

来源:互联网 发布:淘宝评价解释在哪里 编辑:程序博客网 时间:2024/06/03 21:42

SPOJ - LCS2

求多个字符串的最长公共子串。先构造第一个串的后缀自动机,定义一个nl表示当前字符串在该处与后缀自动机匹配的最大长度,ml用于保存所有字符串在该处都能匹配的长度,不断更新。

#include <stdio.h>#include <string.h>#include <iostream>#include <algorithm>#include <vector>#include <queue>#include <stack>#include <set>#include <map>#include <string>#include <math.h>#include <stdlib.h>#include <time.h>#include <bitset>#define INF 0x3f3f3f3f#define eps 1e-6#define PI 3.1415926#define mod 1000000009#define base 2333using namespace std;typedef long long LL;const int maxn = 1e5 + 10;const int maxx = 1e3 + 10;inline void splay(int &v) {    v=0;char c=0;int p=1;    while(c<'0' || c >'9'){if(c=='-')p=-1;c=getchar();}    while(c>='0' && c<='9'){v=(v<<3)+(v<<1)+c-'0';c=getchar();}    v*=p;}struct Node {    Node *pre, *nxt[26];    int step, nl, ml;    void Clear() {        step = nl = 0;        pre = NULL;        memset(nxt, NULL, sizeof(nxt));    }} *root, *last;Node st[maxn<<1], *top[maxn<<1], *cur;int cnt[maxn];char str[15][maxn];void init() {    cur = st;    root = last = cur++;    root->Clear();}void extend(int w) {    Node *np = cur++, *p = last;    np->Clear();    np->step = np->ml = p->step+1;    while(p && !p->nxt[w])        p->nxt[w] = np, p = p->pre;    if(p == NULL)        np->pre = root;    else {        Node *q = p->nxt[w];        if(q->step == p->step+1)            np->pre = q;        else {            Node *nq = cur++;            nq->Clear();            memcpy(nq->nxt, q->nxt, sizeof(q->nxt));            nq->step = nq->ml = p->step+1;            nq->pre = q->pre;            np->pre = q->pre = nq;            while(p && p->nxt[w] == q)                p->nxt[w] = nq, p = p->pre;        }    }    last = np;}void solve() {    int k = 0;    while(scanf("%s", str[k++]) != EOF) {}    init();    memset(cnt, 0, sizeof(cnt));    int len = strlen(str[0]);    for(int i = 0; i < len; i++)        extend(str[0][i]-'a');    for(Node *p = st; p != cur; p++)        cnt[p->step]++;    for(int i = 1; i <= len; i++)        cnt[i] += cnt[i-1];    for(Node *p = st; p != cur; p++)        top[--cnt[p->step]] = p;    int num = cur-st;    for(int i = 1; i < k-1; i++) {        int len1 = strlen(str[i]);        Node *p = root;        for(int j = 0, l = 0; j < len1; j++) {            int x = str[i][j]-'a';            if(p->nxt[x])                l++, p = p->nxt[x];            else {                while(p && !p->nxt[x])                    p = p->pre;                if(p == NULL)                    l = 0, p = root;                else                    l = p->step+1, p = p->nxt[x];            }            if(l > p->nl) p->nl = l;        }        for(int j = num-1; j >= 0; j--) {            p = top[j];            if(p->nl < p->ml)                p->ml = p->nl;            if(p->pre && p->pre->nl < p->nl)                p->pre->nl = p->nl;            p->nl = 0;        }    }    int ans = 0;    for(int i = 0; i < num; i++)        ans = max(ans, top[i]->ml);    printf("%d\n", ans);}int main() {    //srand(time(NULL));    //freopen("kingdom.in","r",stdin);    //freopen("kingdom.out","w",stdout);    solve();}


原创粉丝点击