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
原文地址:https://www.cnblogs.com/DOLFAMINGO/p/8473596.html