zoukankan      html  css  js  c++  java
  • POJ 2774 Long Long Message

    题意:给两个字符串,求公共连续子串的长度。

    解法:后缀数组。看大白学了一下,讲的还挺详细的……不过还有一些细节没弄懂……赛后再学吧……先把模板用明白再说……

    sa[i]表示将字符串的后缀排序后排名第i的字符串序号。

    rank[i]表示第i个后缀在sa中的下标。

    height[i]表示sa[i]和sa[i - 1]的最长公共前缀。

    这道题是将两个字符串连在一起,中间加一个不属于这两个字符串字符集的字符,找到最大的height[i]使sa[i]和sa[i - 1]分别在两个字符串中即为答案。

    代码:

    #include<stdio.h>
    #include<iostream>
    #include<algorithm>
    #include<string>
    #include<string.h>
    #include<math.h>
    #include<limits.h>
    #include<time.h>
    #include<stdlib.h>
    #include<map>
    #include<queue>
    #include<set>
    #include<stack>
    #include<vector>
    #include<iomanip>
    #define LL long long
    #define lson l, m, rt << 1
    #define rson m + 1, r, rt << 1 | 1
    int const MAXN = 200005;
    
    using namespace std;
    char s[MAXN];
    int sa[MAXN], t[MAXN], t2[MAXN], c[MAXN], n, rank[MAXN], height[MAXN];
    void buildsa(int m)//字符串的字符要在0~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;
        }
    }
    void getheight()
    {
        int i, j, k = 0;
        for(i = 0; i < n; i++) rank[sa[i]] = i;
        for(i = 0; i < n; i++)
        {
            if(k) k--;
            int j = sa[rank[i] - 1];
            while(s[i + k] == s[j + k]) k++;
            height[rank[i]] = k;
        }
    }
    int main()
    {
        char a[MAXN];
        while(~scanf("%s%s", s, a))
        {
            int len = strlen(s);
            s[len] = '$';
            s[len + 1] = '';
            strcat(s, a);
            n = strlen(s);
            buildsa(256);
            getheight();
            int maxn = 0;
            for(int i = 1; i < n; i++)
            {
                if(maxn < height[i])
                {
                    if(sa[i - 1] < len && sa[i] > len) maxn = height[i];
                    if(sa[i] < len && sa[i - 1] > len) maxn = height[i];
                }
            }
            cout << maxn << endl;
        }
        return 0;
    }
    

      

  • 相关阅读:
    微信公众平台消息接口开发之校验签名与消息响应合并
    微信公众平台开发之在网页上添加分享到朋友圈,关注微信号等按钮
    微信公众平台自定义菜单PHP开发
    所有边权均不相同的无向图最小生成树是唯一的证明
    无向带权图的最小生成树算法——Prim及Kruskal算法思路
    排序二叉树,平衡二叉树和红黑树的概念以及相关的操作讲解
    B树、B-树、B+树、B*树
    森林、树与二叉树相互转换
    普通树转换成二叉树
    哈夫曼树
  • 原文地址:https://www.cnblogs.com/Apro/p/4877660.html
Copyright © 2011-2022 走看看