We split/block enumeration of answer X, and the brute force of the X-length substring hash of the string other than the shortest string is thrown into the set.
Then violently enumerate the X-length strings of the shortest string to see if they appear in all set.
#include <cstdio> #include <set> #include <cstring> #include <cmath>using namespace Std;typedef unsigned long long ull;set<ull>t[6];const ull seed=29;ull seeds[2001],ord[301];int N,ls[6],minv=2147483647,mini , Ans;char s[6][2001];ull bkdrhash (const char str[],const int &l,const int &r) {ull res=0; for (int i=l;i<r;++i) res=res*seed+ord[str[i]]; return res;} void Init () {for (int i= ' A ', j=1;i<= ' z '; ++i,++j) ord[i]= (ull) J; Seeds[0]=1; for (int i=1;i<=minv;++i) seeds[i]=seeds[i-1]*seed;} BOOL Find_in_all (const ull &x) {for (int i=1;i<=n;++i) if (I!=mini) if (T[i].find (x) ==t[i].end ()) return 0;ret Urn 1;} BOOL Check (const int &x) {for (int i=1;i<=n;++i) if (I!=mini) {t[i].clear (); Ull Hs=bkdrhash (s[i],0,x); T[i].insert (HS); for (int j=x;j<ls[i];++j) {hs=hs*seed+ord[s[i][j]]; Hs-=seeds[x]*ord[s[i][j-x]]; T[i].insert (HS); }}ull Hs=bkdrhash (s[mini],0,x), if (Find_in_all (HS)) return 1;for (int i=x;i< minv;++i) {hs=hs*seed+ord[s[mini][i]]; Hs-=seeds[x]*ord[s[mini][i-x]]; if (Find_in_all (HS)) return 1; }return 0;} int main () {scanf ("%d", &n), for (int i=1;i<=n;++i) {scanf ("%s", S[i]); Ls[i]=strlen (S[i]); if (LS[I]<MINV) {minv=ls[i]; Mini=i; }}init (); int sz=sqrt (MINV), last=minv+1; for (int i=minv;last;i-=sz) {if (check (i)) for (int j=last-1;j>=i;--j) if (check (j)) {printf ("%d\n", j); return 0; } last=i; }}
"dichotomy answer" "Chunk answer" "String hash" "Set" bzoj2946 [Poi2000] Common string