后缀数组+二分。。。思路很简单,把所有的串合并成一个串,串与串之间用不同的且从未出现过的单词隔开。。然后二分答案,找是否存在height数组连续大于等于当前二分的长度且分属于所有的串。。。。
#include <iostream> #include <sstream> #include <algorithm> #include <vector> #include <queue> #include <stack> #include <map> #include <set> #include <bitset> #include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <climits> #define maxn 800005 #define eps 1e-6 #define mod 10007 #define INF 99999999 #define lowbit(x) (x&(-x)) //#define lson o<<1, L, mid //#define rson o<<1 | 1, mid+1, R typedef long long LL; using namespace std; char str[205]; int s[maxn]; int hash[maxn]; int vis[4005]; int sa[maxn], t[maxn], t2[maxn], c[maxn]; int rank[maxn], height[maxn]; int nn; int read(void) { int n = 0, i, j, cnt = 50, len; for(i = 1; i <= nn; i++) { scanf("%s", str); len = strlen(str); for(j = 0; j < len; j++) hash[n] = i, s[n++] = str[j] - 'a' + 1; hash[n] = 0; s[n++] = cnt++; } s[n] = 0; return n; } void build(int n, int m) { int i, k, p, *x = t, *y = t2; 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(k = 1; k <= n; k<<=1) { 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 getheight(int n) { 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++; height[rank[i]] = k; } } bool check(int len, int n) { int cnt = 0, i; memset(vis, 0, sizeof vis); vis[0] = 1; for(i = 1; i <= n; i++) { if(height[i] >= len) { if(!vis[hash[sa[i-1]]]) vis[hash[sa[i-1]]] = 1, cnt++; if(!vis[hash[sa[i]]]) vis[hash[sa[i]]] = 1, cnt++; if(cnt >= nn) return 1; } else { memset(vis, 0, sizeof vis); vis[0] = 1; cnt = 0; } } return 0; } void search(int n) { int bot = 0, top = strlen(str), mid, res = 0, cnt, i, j; while(top >= bot) { mid = (top+bot)>>1; if(check(mid, n)) bot = mid+1, res = mid; else top = mid-1; } if(res == 0) { printf("IDENTITY LOST\n"); return; } memset(vis, 0, sizeof vis); vis[0] = 1, cnt = 0; for(i = 1; i <= n; i++) { if(height[i] >= res) { if(!vis[hash[sa[i-1]]]) vis[hash[sa[i-1]]] = 1, cnt++; if(!vis[hash[sa[i]]]) vis[hash[sa[i]]] = 1, cnt++; if(cnt >= nn) break; } else { memset(vis, 0, sizeof vis); vis[0] = 1; cnt = 0; } } for(j = sa[i]; j < sa[i]+res; j++) printf("%c", s[j]+'a'-1); printf("\n"); } void debug(int n) { int i; for(i = 1; i <= n; i++) printf("%d\n", height[i]); } int main(void) { int n; while(scanf("%d", &nn), nn!=0) { n = read(); build(n+1, 4100); getheight(n); search(n); } return 0; }