POJ 2217

    xiaoxiao2021-03-25  142

    题目大意是给定两个字符串,求两个字符串的最长公共子串。 网上大部分给的都是LCP啊..? 我的第一想法就是二分子串的长度,开始想用哈希搞一搞,后来发现还是还是后缀数组扎实。 所以二分子串长度,当找到一个长度可以使一个字符串s1中的子串在字符串s2中出现,长度++,保存答案,否则-- 然后后缀数组来查询就好了。 #include <cstdio> #include <cstring> #include <algorithm> #include <vector> using namespace std; const int maxn = 10000 + 10; int lenB, lenA; int t[maxn], t2[maxn], sa[maxn], c[maxn]; char B[maxn], A[maxn]; int mp[maxn], m, n; void SA(){ n = lenB; int *x = t, *y = t2; for(int i = 0; i < m; ++i) c[i] = 0; for(int i = 0; i < n; ++i) c[x[i] = mp[(int)B[i]]]++; for(int i = 1; i < m; ++i) c[i] += c[i - 1]; for(int i = n - 1; i >= 0; --i) sa[--c[x[i]]] = i; for(int k = 1; k <= n; k<<=1) { int p = 0; for(int i = n - k; i < n; ++i) y[p++] = i; for(int i = 0; i < n; ++i) if(sa[i] >= k) y[p++] = sa[i] - k; for(int i = 0; i < m; ++i) c[i] = 0; for(int i = 0; i < n; ++i) c[x[y[i]]]++; for(int i = 1; i < m; ++i) c[i] += c[i - 1]; for(int i = n - 1; i >= 0; --i) sa[--c[x[y[i]]]] = y[i]; swap(x, y); p = 1; x[sa[0]] = 0; for(int i = 1; i < n; ++i) { x[sa[i]] = y[sa[i]] == y[sa[i - 1]] && y[sa[i] + k] == y[sa[i - 1] + k] ? p - 1:p++; } if(p >= n) break; m = p; } } int lenm; int cmp(char *pattern, int pos){ return strncmp(pattern, B + sa[pos], lenm); } int find(char *p, int tmp) { lenm = tmp; if(cmp(p, 0) < 0) return -1; if(cmp(p, n - 1) > 0) return -1; // printf("fuck\n"); int L = 0, R = n - 1; while(R >= L) { int M = L + (R - L) / 2; int res = cmp(p, M); if(!res) return M; if(res < 0) R = M - 1; else L = M + 1; } return -1; } bool can(int tmp){ for(int i = 0; i + tmp <= lenA; ++i) { if(find(A + i, tmp) != -1) { return true; } } return false; } void solve(){ int x = 1, y = lenA; int ans = 0; while(x <= y){ int M = x + (y - x) / 2; if(can(M)) { ans = M; x = M + 1; }else{ y = M - 1; } } printf("Nejdelsi spolecny retezec ma delku %d.\n", ans); } void init(){ memset(mp, -1, sizeof(mp)); vector<int> vs; m = 0; for(int i = 0; i < lenB; ++i) { if(mp[(int)B[i]] == -1) { mp[(int)B[i]] = m++; vs.push_back((int)B[i]); } } sort(vs.begin(), vs.end()); m = 0; for(int i = 0; i < (int)vs.size(); ++i) { int ch = vs[i]; mp[ch] = m++; } SA(); } int main(int argc, char const *argv[]) { int T; scanf("%d", &T); getchar(); while(T--){ gets(B); gets(A); lenB = strlen(B), lenA = strlen(A); init(); solve(); } return 0; }
    转载请注明原文地址: https://ju.6miu.com/read-4663.html

    最新回复(0)