zoukankan      html  css  js  c++  java
  • [POJ1226]Substrings(后缀数组)

    传送门

    给定 n 个字符串,求出现或反转后出现在每个字符串中的最长子串。

    算法分析:

    这题不同的地方在于要判断是否在反转后的字符串中出现。其实这并没有加大题目的难度。

    只需要先将每个字符串都反过来写一遍,中间用一个互不相同的且没有出现在字符串中的字符隔开,

    再将 n 个字符串全部连起来,中间也是用一个互不相同的且没有出现在字符串中的字符隔开,求后缀数组。

    然后二分答案,再将后缀分组。

    判断的时候,要看是否有一组后缀在每个原来的字符串或反转后的字符串中出现。

    这个做法的时间复杂度为 O(nlogn)。

    ——代码

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <iostream>
      4 #define N 21001
      5 
      6 int len, n, m, max_num, T;
      7 int buc[N], x[N], y[N], sa[N], rank[N], height[N], belong[N], s[N];
      8 char a[N];
      9 bool f[101];
     10 
     11 inline void build_sa()
     12 {
     13     int i, k, p;
     14     for(i = 0; i < m; i++) buc[i] = 0;
     15     for(i = 0; i < len; i++) buc[x[i] = s[i]]++;
     16     for(i = 1; i < m; i++) buc[i] += buc[i - 1];
     17     for(i = len - 1; i >= 0; i--) sa[--buc[x[i]]] = i;
     18     for(k = 1; k <= len; k <<= 1)
     19     {
     20         p = 0;
     21         for(i = len - 1; i >= len - k; i--) y[p++] = i;
     22         for(i = 0; i < len; i++) if(sa[i] >= k) y[p++] = sa[i] - k;
     23         for(i = 0; i < m; i++) buc[i] = 0;
     24         for(i = 0; i < len; i++) buc[x[y[i]]]++;
     25         for(i = 1; i < m; i++) buc[i] += buc[i - 1];
     26         for(i = len - 1; i >= 0; i--) sa[--buc[x[y[i]]]] = y[i];
     27         std::swap(x, y);
     28         p = 1, x[sa[0]] = 0;
     29         for(i = 1; i < len; i++)
     30             x[sa[i]] = y[sa[i - 1]] == y[sa[i]] && y[sa[i - 1] + k] == y[sa[i] + k] ? p - 1 : p++;
     31         if(p >= len) break;
     32         m = p;
     33     }
     34 }
     35 
     36 inline void build_height()
     37 {
     38     int i, j, k = 0;
     39     for(i = 0; i < len; i++) rank[sa[i]] = i;
     40     for(i = 0; i < len; i++)
     41     {
     42         if(!rank[i]) continue;
     43         if(k) k--;
     44         j = sa[rank[i] - 1];
     45         while(s[i + k] == s[j + k] && i + k < len && j + k < len) k++;
     46         height[rank[i]] = k;
     47     }
     48 }
     49 
     50 inline bool check(int k)
     51 {
     52     int i, cnt = 1;
     53     memset(f, 0, sizeof(f));
     54     f[belong[sa[0]]] = 1;
     55     for(i = 1; i < len; i++)
     56         if(height[i] >= k && !f[belong[sa[i]]])
     57         {
     58             cnt++;
     59             f[belong[sa[i]]] = 1;
     60             if(cnt == n) return 1;
     61         }
     62         else if(height[i] < k)
     63         {
     64             cnt = 1;
     65             memset(f, 0, sizeof(f));
     66             f[belong[sa[i]]] = 1;
     67         }
     68     return 0;
     69 }
     70 
     71 inline int solve()
     72 {
     73     int l = 1, r = len, ans = 0, mid;
     74     while(l <= r)
     75     {
     76         mid = (l + r) >> 1;
     77         if(check(mid)) ans = mid, l = mid + 1;
     78         else r = mid - 1;
     79     }
     80     return ans;
     81 }
     82 
     83 int main()
     84 {
     85     int i, j, l;
     86     scanf("%d", &T);
     87     while(T--)
     88     {
     89         len = 0;
     90         m = 400;
     91         scanf("%d", &n);
     92         for(i = 0; i < n; i++)
     93         {
     94             scanf("%s", a);
     95             l = strlen(a);
     96             for(j = 0; j < l; j++) belong[len] = i, s[len++] = a[j];
     97             belong[len] = i;
     98             s[len++] = 130 + (i << 1);
     99             for(j = l - 1; j >= 0; j--) belong[len] = i, s[len++] = a[j];
    100             belong[len] = i;
    101             s[len++] = 130 + (i << 1 | 1);
    102         }
    103         len--;
    104         build_sa();
    105         build_height();
    106         if(n == 1)
    107         {
    108             printf("%d
    ", l);
    109             continue;
    110         }
    111         printf("%d
    ", solve());
    112     }
    113     return 0;
    114 }
    View Code
  • 相关阅读:
    Windows Phone 8 开发环境搭建
    常用正则表达式大全分享
    ios 使用NSRegularExpression解析正则表达式
    大整数类BIGN的设计与实现 C++高精度模板
    CODEVS_1227 方格取数2 网络流 最小费用流 拆点
    CODEVS_1034 家园 网络流 最大流
    CODEVS_1033 蚯蚓的游戏问题 网络流 最小费用流 拆点
    HDU_4770 Lights Against Dudely 状压+剪枝
    CODEVS_2144 砝码称重 2 折半搜索+二分查找+哈希
    CODEVS_1074 食物链
  • 原文地址:https://www.cnblogs.com/zhenghaotian/p/6999266.html
Copyright © 2011-2022 走看看