zoukankan      html  css  js  c++  java
  • POJ1226 Substrings ——后缀数组 or 暴力+strstr()函数 最长公共子串

    题目链接:https://vjudge.net/problem/POJ-1226

    Substrings
    Time Limit: 1000MS   Memory Limit: 10000K
    Total Submissions: 15122   Accepted: 5309

    Description

    You are given a number of case-sensitive strings of alphabetic characters, find the largest string X, such that either X, or its inverse can be found as a substring of any of the given strings.

    Input

    The first line of the input contains a single integer t (1 <= t <= 10), the number of test cases, followed by the input data for each test case. The first line of each test case contains a single integer n (1 <= n <= 100), the number of given strings, followed by n lines, each representing one string of minimum length 1 and maximum length 100. There is no extra white space before and after a string.

    Output

    There should be one line per test case containing the length of the largest string found.

    Sample Input

    2
    3
    ABCD
    BCDFF
    BRCD
    2
    rose
    orchid

    Sample Output

    2
    2 

    Source

    题意:

    给出n个字符串,问是否存在一个公共子串存在于每个字符串或其逆串中,若存在,输出最长的长度。

    题解:

    1.将所有字符串已经其逆串拼接在一起,相邻两个之间用各异的分隔符隔开。

    2.求出新串的后缀数组,然后二分公共子串的长度mid:mid将新串的后缀分成若干组,每一组对应着一个公共子串,并且长度>=mid。如果这组出现了所有字符串,那么说明当前mid合法,否则不合法。最终求得答案。

    3.由于数据较弱,还可以直接暴力+kmp/strstr()函数。

    后缀数组:

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <algorithm>
      5 #include <vector>
      6 #include <cmath>
      7 #include <queue>
      8 #include <stack>
      9 #include <map>
     10 #include <string>
     11 #include <set>
     12 using namespace std;
     13 typedef long long LL;
     14 const int INF = 2e9;
     15 const LL LNF = 9e18;
     16 const int MOD = 1e9+7;
     17 const int MAXN = 1e5+100;
     18 
     19 int id[MAXN];
     20 int r[MAXN], sa[MAXN], Rank[MAXN], height[MAXN];
     21 int t1[MAXN], t2[MAXN], c[MAXN];
     22 
     23 bool cmp(int *r, int a, int b, int l)
     24 {
     25     return r[a]==r[b] && r[a+l]==r[b+l];
     26 }
     27 
     28 void DA(int str[], int sa[], int Rank[], int height[], int n, int m)
     29 {
     30     n++;
     31     int i, j, p, *x = t1, *y = t2;
     32     for(i = 0; i<m; i++) c[i] = 0;
     33     for(i = 0; i<n; i++) c[x[i] = str[i]]++;
     34     for(i = 1; i<m; i++) c[i] += c[i-1];
     35     for(i = n-1; i>=0; i--) sa[--c[x[i]]] = i;
     36     for(j = 1; j<=n; j <<= 1)
     37     {
     38         p = 0;
     39         for(i = n-j; i<n; i++) y[p++] = i;
     40         for(i = 0; i<n; i++) if(sa[i]>=j) y[p++] = sa[i]-j;
     41 
     42         for(i = 0; i<m; i++) c[i] = 0;
     43         for(i = 0; i<n; i++) c[x[y[i]]]++;
     44         for(i = 1; i<m; i++) c[i] += c[i-1];
     45         for(i = n-1; i>=0; i--) sa[--c[x[y[i]]]] = y[i];
     46 
     47         swap(x, y);
     48         p = 1; x[sa[0]] = 0;
     49         for(i = 1; i<n; i++)
     50             x[sa[i]] = cmp(y, sa[i-1], sa[i], j)?p-1:p++;
     51 
     52         if(p>=n) break;
     53         m = p;
     54     }
     55 
     56     int k = 0;
     57     n--;
     58     for(i = 0; i<=n; i++) Rank[sa[i]] = i;
     59     for(i = 0; i<n; i++)
     60     {
     61         if(k) k--;
     62         j = sa[Rank[i]-1];
     63         while(str[i+k]==str[j+k]) k++;
     64         height[Rank[i]] = k;
     65     }
     66 }
     67 
     68 bool vis[110];
     69 bool test(int n, int len, int k)
     70 {
     71     int cnt = 0;
     72     memset(vis, false, sizeof(vis));
     73     for(int i = 2; i<=len; i++)
     74     {
     75         if(height[i]<k)
     76         {
     77             cnt = 0;
     78             memset(vis, false, sizeof(vis));
     79         }
     80         else
     81         {
     82             if(!vis[id[sa[i-1]]]) vis[id[sa[i-1]]] = true, cnt++;
     83             if(!vis[id[sa[i]]]) vis[id[sa[i]]] = true, cnt++;
     84             if(cnt==n) return true;
     85         }
     86     }
     87     return false;
     88 }
     89 
     90 char str[MAXN];
     91 int main()
     92 {
     93     int T, n;
     94     scanf("%d", &T);
     95     while(T--)
     96     {
     97         scanf("%d", &n);
     98         int len = 0;
     99         for(int i = 0; i<n; i++)
    100         {
    101             scanf("%s", str);
    102             int LEN = strlen(str);
    103             for(int j = 0; j<LEN; j++)
    104             {
    105                 r[len] = str[j];
    106                 id[len++] = i;
    107             }
    108             r[len] = 130+i; //分隔符
    109             id[len++] = i;
    110         }
    111         for(int i = 0; i<len; i++)  //逆串
    112         {
    113             r[2*len-1-i] = r[i];
    114             if(r[2*len-1-i]>=130) r[2*len-1-i] += 120;  //分隔符应各异
    115             id[2*len-1-i] = id[i];
    116         }
    117         len *= 2;
    118         r[len] = 0;
    119         DA(r,sa,Rank,height,len,400);
    120 
    121         int l = 0, r = 100;
    122         while(l<=r)
    123         {
    124             int mid = (l+r)>>1;
    125             if(test(n,len,mid))
    126                 l = mid + 1;
    127             else
    128                 r = mid - 1;
    129         }
    130         printf("%d
    ", r);
    131     }
    132 }
    View Code

    暴力 + strstr()函数:

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <cstdlib>
     5 #include <string>
     6 #include <vector>
     7 #include <map>
     8 #include <set>
     9 #include <queue>
    10 #include <sstream>
    11 #include <algorithm>
    12 using namespace std;
    13 typedef long long LL;
    14 const double eps = 1e-6;
    15 const int INF = 2e9;
    16 const LL LNF = 9e18;
    17 const int MOD = 1e9+7;
    18 const int MAXN = 100+10;
    19 
    20 char s[MAXN][MAXN], t1[MAXN], t2[MAXN];
    21 
    22 int main()
    23 {
    24     int T, n;
    25     scanf("%d", &T);
    26     while(T--)
    27     {
    28         scanf("%d", &n);
    29         for(int i = 1; i<=n; i++)
    30             scanf("%s", s[i]);
    31 
    32         int Len = strlen(s[1]), ans = 0;
    33         for(int len = Len; len>=1; len--)
    34         {
    35             for(int st = 0; st<=Len-len; st++)
    36             {
    37                 int en = st+len-1, cnt = 0;
    38                 for(int i = st; i<=en; i++)
    39                 {
    40                     t1[cnt] = s[1][i];
    41                     t2[cnt++] = s[1][i];
    42                 }
    43                 t1[cnt] = t2[cnt] = 0;
    44                 reverse(t2,t2+cnt);
    45 
    46                 bool flag = true;
    47                 for(int i = 2; i<=n; i++)
    48                     flag = flag&&(strstr(s[i], t1) || strstr(s[i], t2) );
    49 
    50                 if(flag)
    51                 {
    52                     ans = len;
    53                     break;
    54                 }
    55             }
    56             if(ans==len) break;
    57         }
    58         printf("%d
    ", ans);
    59     }
    60 }
    View Code
  • 相关阅读:
    CentOS下安装vsftpd
    Linux下快速删除大量文件
    /var/spool/postfix/maildrop/ 中有大量的文件
    Linux 查看目录大小及文件数量命令
    windows下体验Redis
    hMailServer SSL 配置
    vmware 安装 Mac OS X 10.9 Mavericks
    提问和看不懂
    C 语言学习 第三次作业总结
    C 语言学习 第二次作业总结
  • 原文地址:https://www.cnblogs.com/DOLFAMINGO/p/8473596.html
Copyright © 2011-2022 走看看