"topic link" http://www.spoj.pl/problems/PHRASES/
"the Main topic"
The longest substring that appears at least two times in each string
Exercises
Notice a few key points: the longest, at least two times, per String.
First for the longest this condition, we can think of the Two-point answer,
It then uses the three arrays of the suffix array to determine whether the condition is Satisfied.
And then there are two times, and every time this condition occurs,
We should think of this as the maximum minimum value that can be handled,
Save the starting position of each identical string that appears in the same string,
If the gap between the minimum and maximum values exceeds the length of two l, then it is possible that this condition is feasible in this string.
Concatenate all the strings together by concatenation, doing the suffix array again,
Now we are going to divide the suffix into a group of more than two lengths according to the H array,
Whenever there is a number of suffixes in a grouping greater than 2*n,
That means the string might be the answer we need, then it's tested,
The judgment of a length can be done by examining all possible valid strings.
Code
#include <cstdio> #include <cstring> #include <vector> #include <algorithm>using namespace std; const INT N=1000010;int n,m,rank[n],sa[n],h[n],tmp[n],cnt[n],ans,a[n],s[n]; Char str[n];void suffixarray (int n,int m) {int i,j,k;n++; For (i=0;i<2*n+5;i++) rank[i]=sa[i]=h[i]=tmp[i]=0; For (i=0;i<m;i++) cnt[i]=0; For (i=0;i<n;i++) cnt[rank[i]=s[i]]++; For (i=1;i<m;i++) cnt[i]+=cnt[i-1]; For (i=0;i<n;i++) sa[--cnt[rank[i]]]=i; For (k=1;k<=n;k<<=1) {for (i=0;i<n;i++) {j=sa[i]-k; If (j<0) j+=n; tmp[cnt[rank[j]]++]=j; }sa[tmp[cnt[0]=0]]=j=0; For (i=1;i<n;i++) {if (rank[tmp[i]]!=rank[tmp[i-1]]| | Rank[tmp[i]+k]!=rank[tmp[i-1]+k]) cnt[++j]=i; sa[tmp[i]]=j; }memcpy (rank,sa,n*sizeof (int)); memcpy (sa,tmp,n*sizeof (int)); If (j>=n-1) break; }for (j=rank[h[i=k=0]=0];i<n-1;i++,k++) while (~k&&s[i]!=s[sa[j-1]+k]) h[j]=k--, j=rank[sa[j]+1];} InchT first=0,len[n],u,k;vector<int> s[n];int min[15],max[15];bool check (int L) {int cur=-1; For (int i=1;i<=u;i++) {if (h[i]<l) s[++cur].clear (); S[cur].push_back (i); } for (int i=0;i<=cur;i++) {if (s[i].size () >=2*n) {memset (min,-1,sizeof (Min)); Memset (max,-1,sizeof (Max)); For (int j=0;j<s[i].size (); j + +) {int k=s[i][j]; int X=upper_bound (a,a+n+1,sa[k])-a-1; Min[x]=min[x]==-1?sa[k]:min (min[x],sa[k]); Max[x]=max[x]==-1?sa[k]:max (max[x],sa[k]); }bool flag=1; For (int i=0;i<n;i++) {if (min[i]==-1| | Max[i]-min[i]<l) {flag=0;break;} }if (flag) return 1; }}return 0;} int T;int main () {scanf ("%d", &t); While (t--) {scanf ("%d", &n); int tmp=200; u=0; For (int i=0;i<n;i++) {scanf ("%s", str); len[i]=strlen (str); For (int j=0;j<len[i];j++) s[u++]= (int) str[j];s[u++]=tmp++; }tmp=0; s[u]=0; Note that the finished string is last sealed with 0 for (int I=0;i<=n;i++) {a[i]=tmp; If (i<n) tmp=tmp+ (i==0?len[i]:len[i]+1); }suffixarray (u,310); int l=1,r=10000,ans=0; While (l<=r) {int mid= (l+r) >>1; If (check (MID)) ans=mid,l=mid+1; else r=mid-1; }printf ("%d\n", ans); }return 0;}
Spoj relevant phrases of annihilation (suffix array + dichotomy Answer)