• hdu2328(后缀数组 + 二分)


    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=2328

    题意: 求 n 个串的字典序最小的最长公共子串

    思路: 本题中单个字符串长度不超过 200, 可以暴力枚举一个字符串的所有前缀, 然后用kmp去匹配其他字符串.

    我这里是用后缀数组写的. 类似 http://www.cnblogs.com/geloutingyu/p/7450580.html

    不过本题是有 n 个字符串, 不能直接暴力判断. 不难想到这里可以直接二分答案长度, 不过 check 函数比较难想到, 具体看代码

    代码:

      1 #include <iostream>
      2 #include <stdio.h>
      3 #include <string.h>
      4 #define rank Rank
      5 using namespace std;
      6 
      7 const int MAXN = 1e6 + 10;
      8 int sol;
      9 char str[MAXN];
     10 int SA[MAXN], rank[MAXN], height[MAXN], sum[MAXN], tp[MAXN], vis[MAXN], tag[(int)(4e3 + 10)];
     11 
     12 bool cmp(int *f, int x, int y, int w){
     13     return f[x] == f[y] && f[x + w] == f[y + w];
     14 }
     15 
     16 void DA(char *s, int n, int m){
     17     for(int i = 0; i < m; i++) sum[i] = 0;
     18     for(int i = 0; i < n; i++) sum[rank[i] = s[i]]++;
     19     for(int i = 1; i < m; i++) sum[i] += sum[i - 1];
     20     for(int i = n - 1; i >= 0; i--) SA[--sum[rank[i]]] = i;
     21     for(int len = 1; len <= n; len <<= 1){
     22         int p = 0;
     23         for(int i = n - len; i < n; i++) tp[p++] = i;
     24         for(int i = 0; i < n; i++){
     25             if(SA[i] >= len) tp[p++] = SA[i] - len;
     26         }
     27         for(int i = 0; i < m; i++) sum[i] = 0;
     28         for(int i = 0; i < n; i++) sum[rank[tp[i]]]++;
     29         for(int i = 1; i < m; i++) sum[i] += sum[i - 1];
     30         for(int i = n - 1; i >= 0; i--) SA[--sum[rank[tp[i]]]] = tp[i];
     31         swap(rank, tp);
     32         p = 1;
     33         rank[SA[0]] = 0;
     34         for(int i = 1; i < n; i++){
     35             rank[SA[i]] = cmp(tp, SA[i - 1], SA[i], len) ? p - 1 : p++;
     36         }
     37         if(p >= n) break;
     38         m = p;
     39     }
     40     int k = 0;
     41     n--;
     42     for(int i = 0; i <= n; i++) rank[SA[i]] = i;
     43     for(int i = 0; i < n; i++){
     44         if(k) k--;
     45         int j = SA[rank[i] - 1];
     46         while(s[i + k] == s[j + k]) k++;
     47         height[rank[i]] = k;
     48     }
     49 }
     50 
     51 bool check(int mid, int n, int len){
     52     int cnt = 1;
     53     memset(tag, 0, sizeof(tag));
     54     tag[vis[SA[1]]] = 1;
     55     for(int i = 2; i <= len; i++){
     56         if(height[i] >= mid){
     57             if(!tag[vis[SA[i]]]){
     58                 cnt++;
     59                 tag[vis[SA[i]]] = 1;
     60                 if(cnt >= n){
     61                     sol = SA[i];
     62                     return true;
     63                 }
     64             }
     65         }else{
     66             cnt = 1;
     67             memset(tag, 0, sizeof(tag));
     68             tag[vis[SA[i]]] = 1;
     69         }
     70     }
     71     return false;
     72 }
     73 
     74 int main(void){
     75     int n;
     76     while(~scanf("%d", &n) && n){
     77         memset(vis, 0, sizeof(vis));
     78         scanf("%s", str);
     79         int len = strlen(str);
     80         int mx = len;
     81         for(int i = 1; i < n; i++){
     82             vis[len] = 1;
     83             str[len] = '0';
     84             scanf("%s", str + 1 + len);
     85             mx = max(mx, (int)(strlen(str) - len));
     86             len = strlen(str);
     87         }
     88         str[len] = 0;
     89         DA(str, len + 1, 'z' + 1);
     90         for(int i = 1; i <= len; i++) vis[i] += vis[i - 1];
     91         int l = 1, r = mx;
     92         while(l <= r){
     93             int mid = (l + r) >> 1;
     94             if(check(mid, n, len)) l = mid + 1;
     95             else r = mid - 1;
     96         }
     97         if(l - 1 <= 0){
     98             puts("IDENTITY LOST");
     99             continue;
    100         }
    101         for(int i = sol, j = 1; j <= l - 1; i++, j++){
    102             printf("%c", str[i]);
    103         }
    104         puts("");
    105     }
    106     return 0;
    107 }
    View Code
  • 相关阅读:
    扫面线模板
    (动态规划、栈)leetcode 84. Largest Rectangle in Histogram, 85. Maximal Rectangle
    tmux 常见命令汇总
    leetcode 221
    leetcode 319 29
    (贪心)leetcode 392. Is Subsequence, 771. Jewels and Stones, 463. Island Perimeter
    leetcode 982 668
    Python import 同文件夹下的py文件的函数,pycharm报错
    Windows里Anaconda-Navigator无法打开的解决方案
    Windows下 gpu版 Tensorflow 安装
  • 原文地址:https://www.cnblogs.com/geloutingyu/p/7467440.html
Copyright © 2020-2023  润新知