SPOJ

来源:互联网 发布:pdf.js如何使用 编辑:程序博客网 时间:2024/04/30 19:43

Longest Common Substring

 SPOJ - LCS


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 simple, for two 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 exactly two lines, each line consists of no more than 250000 lowercase letters, representing a string.

Output

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

Example

Input:alsdfkjfjkdsalfdjskalajfkdslaOutput:3

Notice: new testcases added

SourceSPOJ - LCSMy Solution题意:求两个字符串的最长公共子串。
后缀自动机
看了很久 WJMZBMR 讲后缀自动机的ppt才大致把后缀自动机搞懂^_^,
此外附上两个比较好的讲后缀自动机的博客 后缀自动机 模版,后缀自动机讲解
这题直接用一个字符串建立后缀自动机,然后用另一个串在自动机上跑即可,操作和AC自动机有点类似,
只是AC自动机匹配失败的时候用的fail指针,而这里用pre树跳转。
复杂度 O(n)
#include <iostream>#include <cstdio>#include <string>#include <cstring>using namespace std;typedef long long LL;const int maxn = 2*2.5e5 + 8;string s;struct SAM{    int ch[maxn][26], pre[maxn], val[maxn];    int last, tot;    void init(){        last = tot = 0;        memset(ch[0], -1, sizeof ch[0]);        pre[0] = -1; val[0] = 0;    }    void extend(int c){        int p = last, np = ++tot;        val[np] = val[p] + 1;        memset(ch[np], -1, sizeof ch[np]);        while(~p && ch[p][c] == -1) ch[p][c] = np, p = pre[p];        if(p == -1) pre[np] = 0;        else{            int q = ch[p][c];            if(val[q] != val[p] + 1){                int nq = ++tot;                memcpy(ch[nq], ch[q], sizeof ch[q]);                val[nq] = val[p] + 1;                pre[nq] = pre[q];                pre[q] = pre[np] = nq;                while(~p && ch[p][c] == q) ch[p][c] = nq, p = pre[p];            }            else pre[np] = q;        }        last = np;    }    int _find(const string &s){        int sz = s.size(), u = 0, tmp = 0, c, i, res = 0;        for(i = 0; i < sz; i++){            c = s[i] - 'a';            if(~ch[u][c]) tmp++, u = ch[u][c];            else{                while(~u && ch[u][c] == -1) u = pre[u];                if(~u) tmp = val[u] + 1, u = ch[u][c];                else tmp = 0, u = 0;            }            res = max(res, tmp);        }        return res;    }} sam;int main(){    #ifdef LOCAL    freopen("11.in", "r", stdin);    //freopen("11.out", "w", stdout);    int T = 2;    while(T--){    #endif // LOCAL    ios::sync_with_stdio(false); cin.tie(0);    int n, i;    cin >> s;    n = s.size();    sam.init();    for(i = 0; i < n; i++) sam.extend(s[i] - 'a');    cin >> s;    cout << sam._find(s) << endl;;    #ifdef LOCAL    cout << endl;    }    #endif // LOCAL    return 0;}




Thank you!

                                                                                                                                             ------from ProLights

0 0
原创粉丝点击