Long Long Message POJ - 2774(最长公共子串)

题意:

  给你两串字符,要你找出在这两串字符中都出现过的最长子串

解析:

  先用个分隔符将两个字符串连接起来,再用后缀数组求出height数组的值,找出一个height值最大并且i与i-1的sa值分别在两串字符中就好了

#include <iostream>
#include <cstdio>
#include <sstream>
#include <cstring>
#include <map>
#include <cctype>
#include <set>
#include <vector>
#include <stack>
#include <queue>
#include <algorithm>
#include <cmath>
#define rap(i, a, n) for(int i=a; i<=n; i++)
#define rep(i, a, n) for(int i=a; i<n; i++)
#define lap(i, a, n) for(int i=n; i>=a; i--)
#define lep(i, a, n) for(int i=n; i>a; i--)
#define rd(a) scanf("%d", &a)
#define rlld(a) scanf("%lld", &a)
#define rc(a) scanf("%c", &a)
#define rs(a) scanf("%s", a)
#define MOD 2018
#define LL long long
#define ULL unsigned long long
#define Pair pair<int, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define _  ios_base::sync_with_stdio(0),cin.tie(0)
//freopen("1.txt", "r", stdin);
using namespace std;
const int maxn = 200010, INF = 0x7fffffff;
int s[maxn];
int sa[maxn], t[maxn], t2[maxn], c[maxn], n;
int ran[maxn], height[maxn];

void get_sa(int m)
{
    int i, *x = t, *y = t2;
    for(i = 0; i < m; i++) c[i] = 0;
    for(i = 0; i < n; i++) c[x[i] = s[i]]++;
    for(i = 1; i < m; i++) c[i] += c[i-1];
    for(i = n-1; i >= 0; i--) sa[--c[x[i]]] = i;
    for(int k = 1; k <= n; k <<= 1)
    {
        int p = 0;
        for(i = n-k; i < n; i++) y[p++] = i;
        for(i = 0; i < n; i++) if(sa[i] >= k) y[p++] = sa[i] - k;
        for(i = 0; i < m; i++) c[i] = 0;
        for(i = 0; i < n; i++) c[x[y[i]]]++;
        for(i = 0; i< m; i++) c[i] += c[i-1];
        for(i = n-1; i >= 0; i--) sa[--c[x[y[i]]]] = y[i];
        swap(x, y);
        p = 1; x[sa[0]] = 0;
        for(i = 1; i < n; i++)
            x[sa[i]] = y[sa[i-1]] == y[sa[i]] && y[sa[i-1]+k] == y[sa[i]+k] ? p-1 : p++;
        if(p >= n) break;
        m = p;
    }
    int k = 0;
    for(i = 0; i < n; i++) ran[sa[i]] = i;
    for(i = 0; i < n; i++)
    {
        if(k) k--;
        int j = sa[ran[i]-1];
        while(s[i+k] == s[j+k]) k++;
        height[ran[i]] = k;
    }
}

char s1[maxn], s2[maxn];
int main()
{
    while(~scanf("%s%s", s1, s2)){
        n = 0;
        int len1 = strlen(s1);
        rep(i, 0, len1)
            s[n++] = s1[i] - 'a' + 1;

        s[n++] = 28;
        int len2 = strlen(s2);
        rep(i, 0, len2)
            s[n++] = s2[i] - 'a' + 1;
        s[n++] = 0;
        get_sa(30);
        int maxx = -INF;
        rep(i, 1, n)
        {
            if(height[i] > maxx && sa[i] < len1 && sa[i-1] > len1 && sa[i] >= 0)
                maxx = height[i];
            else if(height[i] > maxx && sa[i-1] < len1 && sa[i] > len1 && sa[i-1] >= 0)
                maxx = height[i];
        }
        cout<< maxx <<endl;
    }

    return 0;
}

 

posted @ 2018-08-17 21:39  WTSRUVF  阅读(322)  评论(0编辑  收藏  举报