题意给了n个串 然后计算 这些串中的子串在大于1/2的串中出现 求出这个串的最长长度。 将这些串用一个每出现的不同的字符拼起来 ,然后二分找lcp
#include <iostream> #include <algorithm> #include <string.h> #include <algorithm> #include <vector> #include <cstdio> using namespace std; const int maxn=2005; const int maxm=205; const int MM=maxn*maxm; struct SuffixArray { int s[MM]; // 原始字符数组(最后一个字符应必须是0,而前面的字符必须非0) int sa[MM]; // 后缀数组 int rank[MM]; // 名次数组. rank[0]一定是n-1,即最后一个字符 int height[MM]; // height数组 int t[MM], t2[MM], c[MM]; // 辅助数组 int n; // 字符个数 void clear(){ n=0; } void build(int m) { int *x=t,*y=t2,i; for(i=0; i<m; i++)c[i]=0; for(i=0; i<n; i++)c[ x[i] = s[i] ]++; for(i=1; i<m; i++)c[ i ] += c[ i-1 ]; for(i = n-1; i >= 0; i--) sa[--c[x[i]]] = i; for(int k=1; k<=n; k<<=1) { int p=0; for(i=n-k; i<n; i++)y[p++]=i; for(i=0; i<n; i++)if(sa[i]>=k)y[p++]=sa[i]-k; for(i=0; i<m; i++)c[i]=0; for(i=0; i<n; i++)c[ x[y[ i] ] ]++; for(i=1; i<m; i++)c[i]+=c[i-1]; for(i =n-1; i>=0; i--)sa[ --c[ x[ y[i] ] ] ] = y[i]; swap(x,y); p=1; x[ sa[0] ] =0; for( 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; } } void build_height() { int i, k = 0; for(i = 0; i < n; i++) rank[sa[i]] = i; height[0]=0; for(i = 0; i < n; i++) { if(k) k--; if(rank[i]==0)continue; int j = sa[rank[i]-1]; while(i+k<n&&j+k<n&&s[i+k] == s[j+k]) k++; height[rank[i]] = k; } } }sa; char word[MM]; int idx[MM],n,maxlen; int flag[150]; void add(int ch, int i) { idx[sa.n] = i; sa.s[sa.n++] = ch; } // 子串[L,R) 是否符合要求 bool good(int L, int R,int &ss) { if(R - L <= n/2) return false; int cnt = 0; for(int i = L; i < R; i++) { int x = idx[sa.sa[i]]; if(x != n && flag[x]!=ss) { flag[x] = ss; cnt++; } } return cnt > n/2; } void print_sub(int L, int R) { for(int i = L; i < R; i++) printf("%c", sa.s[i] - 1 + ‘a‘); printf("\n"); } int ss; bool print_solutions(int len, bool print) { int L = 0; ss++; for(int R = 1; R <= sa.n; R++) { if(R == sa.n || sa.height[R] < len) { // 新开一段 if(good(L, R,ss)) { if(print) print_sub(sa.sa[L], sa.sa[L] + len); else return true; } ss++; L = R; } } return false; } void solve(int maxlen) { if(!print_solutions(1, false)) printf("?\n"); else { int L = 1, R = maxlen, M; while(L < R) { M = L + (R-L+1)/2; if(print_solutions(M, false)) L = M; else R = M-1; } print_solutions(L, true); } } int main() { int kase=0; while(scanf("%d",&n)==1) { if(n==0)break; if(kase++>0) puts(""); maxlen=0; sa.clear(); for(int i=0; i<n; i++) { scanf("%s",word); int sz= strlen(word); maxlen=max(sz,maxlen); for(int j=0; j<sz; j++) { add(word[j]-‘a‘+1,i); } add(123+i,n); } add(123+n,n); if(n==1)printf("%s\n",word); else { ss=1; memset(flag,0,sizeof(flag)); sa.build( 123+n+4 ); sa.build_height(); solve(maxlen); } } return 0; }
时间: 2024-10-09 00:44:09