1. 程式人生 > >POJ 2217 (字尾陣列+LCP)

POJ 2217 (字尾陣列+LCP)

要注意最後的空串也要算進去,所以是<=n


#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <string>
#include <set>
#include <vector>
#include <cmath>
#define LL long long
#define eps 1e-8
const LL INF = 0x3f3f3f3f;
const int maxn = 200000
+ 5; using namespace std; int sa[maxn*2]; int t[maxn*2]; int t2[maxn*2]; int c[maxn*2]; int Rank[maxn]; int lcp[maxn]; string s1, s2; void get_lcp(int n, string s){ int i,j,k = 0; for(i=0; i<=n; i++) Rank[sa[i]] = i; for(i=0; i<n; i++){ if(k) k--; j = sa[Rank[i]-1]; while
(s[i+k] == s[j+k]) k++; lcp[Rank[i]-1] = k; } } void build_sa(int n, int m, string s){ int *x = t, *y = t2; n++; for(int i=0; i<m; i++) c[i] = 0; for(int i=0; i<n; i++) c[x[i] = s[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=0; 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-1]] == y[sa[i]] && y[sa[i-1]+k] == y[sa[i]+k] ? p-1 : p++; if(p >= n) break; m = p; } } int main(){ int T; scanf("%d",&T); getchar(); while(T--){ getline(cin,s1); getline(cin,s2); int len = (int)s1.length(); s1 += '#' + s2; int n = (int)s1.length(); build_sa(n,300,s1); get_lcp(n,s1); int ans = 0; for(int i=0; i<n; i++){ if((sa[i] < len) != (sa[i+1] < len)){ ans = max(ans, lcp[i]); } } printf("Nejdelsi spolecny retezec ma delku %d.\n",ans); } }