zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    (整理)SQLServer_DBA 工具
    (转)winform Form 淡入淡出效果
    (转)SQLServer_T-SQL 语句执行时间的查询
    (整理)IIS 7 503 "service unavailable" errors
    (转载)C#中使用GUID
    (转载)SQL Server 2005 如何启用xp_cmdshell组件
    设计模式之适配器
    jaxb 组装及解析xml
    springMvc 简单搭建
    设计模式之工厂模式
  • 原文地址:https://www.cnblogs.com/geloutingyu/p/7467440.html
Copyright © 2011-2022 走看看