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\n", r); 131 } 132 }
暴力 + 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\n", ans); 59 } 60 }