First old routines, we put all the strings together, separated by separators, do SA, find H Array, and the St table for LCP. Then we analyze the topic and we count the answers separately for each string. Suppose we're doing the I-string, starting with the STA in the total string and ending with Ed. What we are asking for is each suffix a[sta...ed],a[sta+1...ed]...a[ed] contribution to the answer and. Suppose we are seeking A[j...ed] to contribute to this suffix. Then his contribution is that there are several prefixes appearing in the different strings of k and above, apparently if a[j. J+len-1] is satisfied and Len is the largest, the contribution to the answer is Len. We only need the biggest len. Considering that if A[j-1...ed] 's contribution to the answer is Len, then A[j...ed's contribution to the answer is at least len-1, and we can seek this contribution as we would for the H array. The
also needs to be implemented to determine whether A[j...j+len-1] (the following is a string T) appears in the different strings of k and above. First, according to the H array we can find the maximum interval [L. R] satisfies this r-l+1 suffix contains a string t. We count whether there are different strings of k or more in this interval. (See the simple procedure later)
optimization, you can find the interval of this [L...R] with two points. The
then is how to quickly determine whether there are different strings of k or more in this interval. We preprocess an L array, which indicates that there are different strings of k and above in the l[i]...i interval and l[i] max. (that is, to make the interval with the right endpoint of I satisfy the minimum interval of the condition) it is clear that this can be done over the O (n) scan. (Use a pointer p to indicate the movement of the left endpoint). You can quickly determine whether the [L...R] interval contains [L[R]...R] intervals. At this point, the problem is resolved. SA positive release
#include <cstdio> #include <cstring> #include <algorithm> #define LL Long long #define N 200010 int n=0,
m=30,nn,kk,a[n],len[n>>1],rank[n<<1],rank1[n],sa[n],h[n],tmp[n],count[n];
int st[n][20],log[n],tot=0,cnt[n>>1],l[n],bel[n];
Char s[n>>1];
inline int min (int x,int y) {return x<y?x:y;} inline int LCP (int l,int R) {++l;
int t=log[r-l+1];
return min (st[l][t],st[r-(1<<t) +1][t]); } bool Check (int x,int length) {//string sa[x]...sa[x]+length-1 whether to meet test instructions int xl,xr;//binary finds the largest [XL...XR] interval, which contains a string sa[x]...sa[x]+le
Ngth-1 if (h[x]<length) xl=x;
else{int l=1,r=x-1;
while (l<=r) {int mid=l+r>>1;
if (LCP (mid,x) >=length) R=mid-1;else l=mid+1;
}xl=l;
} if (h[x+1]<length) xr=x;
else{int l=x+1,r=n;
while (l<=r) {int mid=l+r>>1;
if (LCP (X,mid) >=length) L=mid+1;else r=mid-1;
}xr=r; } return l[xr]>=xl;//L[XR] to XR contains K and more different strings, see if XL...XR can contain} int main () {//Freopen ("A.in", "R", stdin);
scanf ("%d%d", &NN,&KK);
for (int i=1;i<=nn;++i) {scanf ("%s", s+1); Len[i]=strlen (s+1);
for (int j=1;j<=len[i];++j) a[++n]=s[j]-' a ' +1,bel[n]=i;
A[++n]=++m;
}log[0]=-1;
for (int i=1;i<=n;++i) log[i]=log[i>>1]+1;
for (int i=1;i<=m;++i) count[i]=0;
for (int i=1;i<=n;++i) count[a[i]]=1;
for (int i=1;i<=m;++i) count[i]+=count[i-1];
for (int i=n;i>=1;--i) rank[i]=count[a[i]];
int k=0;
for (int p=1;k!=n;p<<=1,m=k) {for (int i=1;i<=m;++i) count[i]=0;
for (int i=1;i<=n;++i) count[rank[i+p]]++;
for (int i=1;i<=m;++i) count[i]+=count[i-1];
for (int i=n;i>=1;--i) tmp[count[rank[i+p]]--]=i;
for (int i=1;i<=m;++i) count[i]=0;
for (int i=1;i<=n;++i) count[rank[tmp[i]]]++;
for (int i=1;i<=m;++i) count[i]+=count[i-1]; for (int i=n;i>=1;--i) Sa[count[ranK[tmp[i]]]--]=tmp[i];
memcpy (rank1,rank,sizeof (RANK1));
rank[sa[1]]=k=1; for (int i=2;i<=n;++i) {if (rank1[sa[i]]!=rank1[sa[i-1]]| |
RANK1[SA[I]+P]!=RANK1[SA[I-1]+P]) ++k;
Rank[sa[i]]=k;
}}k=0;
for (int i=1;i<=n;++i) {if (rank[i]==1) {h[1]=0;continue;} if (i==1| |
H[rank[i-1]]<=1) k=0;
if (k)--k;
while (A[i+k]==a[sa[rank[i]-1]+k]) ++k;
H[rank[i]]=k;
} for (int i=1;i<=n;++i) st[i][0]=h[i]; for (int i=1;i<=log[n];++i) for (int j=1;j<=n;++j) if (j+ (1<<i-1) <=n) st[j][i]=min (st[j][i
-1],st[j+ (1<<i-1)][i-1]);
for (int i=1,p=1;i<=n;++i) {//by rank from small to large if (!bel[sa[i]]) break;
if (cnt[bel[sa[i]]]==0) tot++;
cnt[bel[sa[i]]]++; while (tot>kk| |
TOT==KK&&CNT[BEL[SA[P]]]>1) {//l[i] the right-most value P--cnt[bel[sa[p]]];if (cnt[bel[sa[p++]]]==0)--tot;
} if (TOT>=KK) l[i]=p; else l[I]=-1;
} for (int i=1,sta=1;i<=nn;sta+=len[i++]+1) {ll ans=0;int k=0;
for (int j=sta;j<=sta+len[i]-1;++j) {//statistic the contribution of each suffix of the I-string to the answer if (k)--k;
while (J+k+1-1<=sta+len[i]-1&&check (rank[j],k+1)) ++k;
Ans+=k;
} printf ("%lld", ans); if (I!=NN) printf ("");
} return 0; }
Without two points of complexity is metaphysics, very easily will be data card ... But the 3473 data is really weak ... The violent run 368ms, is the solution to run 1400ms, also gave the 20s time limit ... The
Counter-view 3277 data is very reliable, violent tle ... And the positive solution ran 2496ms. (After all, I'm going to solve Sam ... Cover face) violent version
#include <cstdio> #include <cstring> #include <algorithm> #define LL Long long #define N 200010 int n=0,
m=30,nn,kk,a[n],len[n>>1],rank[n<<1],rank1[n],sa[n],h[n],tmp[n],count[n];
int st[n][20],log[n],tot=0,cnt[n>>1],l[n],bel[n];
Char s[n>>1]; inline int min (int x,int y) {return x<y?x:y;} bool Check (int x,int length) {//String sa[x]...sa[x]+length-1 whether test instructions int l=x is satisfied,
r=x+1;
while (h[l]>=length)--l;
while (h[r]>=length) ++r;--r;
Return l[r]>=l;//L[XR] to XR contains K and more different strings, see if XL...XR can contain} int main () {//Freopen ("A.in", "R", stdin);
scanf ("%d%d", &NN,&KK);
for (int i=1;i<=nn;++i) {scanf ("%s", s+1); Len[i]=strlen (s+1);
for (int j=1;j<=len[i];++j) a[++n]=s[j]-' a ' +1,bel[n]=i;
A[++n]=++m;
}log[0]=-1;
for (int i=1;i<=n;++i) log[i]=log[i>>1]+1;
for (int i=1;i<=m;++i) count[i]=0;
for (int i=1;i<=n;++i) count[a[i]]=1;
for (int i=1;i<=m;++i) count[i]+=count[i-1]; for (int i=n;i>=1;--i) Rank[i]=count[a[i];
int k=0;
for (int p=1;k!=n;p<<=1,m=k) {for (int i=1;i<=m;++i) count[i]=0;
for (int i=1;i<=n;++i) count[rank[i+p]]++;
for (int i=1;i<=m;++i) count[i]+=count[i-1];
for (int i=n;i>=1;--i) tmp[count[rank[i+p]]--]=i;
for (int i=1;i<=m;++i) count[i]=0;
for (int i=1;i<=n;++i) count[rank[tmp[i]]]++;
for (int i=1;i<=m;++i) count[i]+=count[i-1];
for (int i=n;i>=1;--i) sa[count[rank[tmp[i]]]--]=tmp[i];
memcpy (rank1,rank,sizeof (RANK1));
rank[sa[1]]=k=1; for (int i=2;i<=n;++i) {if (rank1[sa[i]]!=rank1[sa[i-1]]| |
RANK1[SA[I]+P]!=RANK1[SA[I-1]+P]) ++k;
Rank[sa[i]]=k;
}}k=0;
for (int i=1;i<=n;++i) {if (rank[i]==1) {h[1]=0;continue;} if (i==1| |
H[rank[i-1]]<=1) k=0;
if (k)--k;
while (A[i+k]==a[sa[rank[i]-1]+k]) ++k;
H[rank[i]]=k; } for (int i=1,p=1;i<=n;++i) {//by rank from small to large if (!bel[sa[i]]) break;
if (cnt[bel[sa[i]]]==0) tot++;
cnt[bel[sa[i]]]++; while (tot>kk| |
TOT==KK&&CNT[BEL[SA[P]]]>1) {//l[i] the right-most value P--cnt[bel[sa[p]]];if (cnt[bel[sa[p++]]]==0)--tot;
} if (TOT>=KK) l[i]=p;
else L[i]=-1;
} for (int i=1,sta=1;i<=nn;sta+=len[i++]+1) {ll ans=0;int k=0;
for (int j=sta;j<=sta+len[i]-1;++j) {//statistic the contribution of each suffix of the I-string to the answer if (k)--k;
while (J+k+1-1<=sta+len[i]-1&&check (rank[j],k+1)) ++k;
Ans+=k;
} printf ("%lld", ans); if (I!=NN) printf ("");
} return 0; }