Question link: http://acm.hdu.edu.cn/showproblem.php? PID = 1, 4416
I feel that this question is not easy to write, all kinds of errors, and finally refer to the blog program and thought to be completed: http://hi.baidu.com/arosliu/item/ec421c23bf862ef951fd8769
According to the previous suffix array writing method, it is no problem to change the run time error to the suffix array on the link above. At present, I don't know where the problem is.
I think the idea of this topic is very clever. It makes good use of the nature of the suffix array and the height array.
First of all, to deal with this problem of multiple strings, it is generally to use a suffix array to concatenate strings and insert a unique character between each string.
So here we will convert all the characters into integer numbers during processing, because if so many unique characters are used
After splicing, calculate SA rank and height, and then find the number of all substrings not needed in this array. This number is better.
After the result is obtained, subtract the number of substrings that contain special characters (which we added when splicing) from the substrings. The result is the number of substrings that do not contain special characters.
In fact, the number of different substrings in all strings (which should be understood here), because len_ AB is added before and len_ B is followed, and the result must be subtracted.
In the same way, find the value that does not contain the first string, and then subtract the two strings to get the result!
How to solve the number of different strings containing special characters is actually the following code
For (I = 0; I <number; I ++)
{
L-= L [I];
Len_ AB-= (L [I] + 1) * l;
L --;
}
L [I] indicates the length of the I-th string, and the initial value of L is equal to the len-1;
Every time we subtract this, why is this correct? Because it contains this special character, the number of different substrings is a combination, take consecutive L [I] + 1, followed by continuous
Different L characters are multiplied by the two. Of course, this is only the case that contains the special character I. As I ++ proceeds, the result will come out!
/*4416*/#include <iostream>#include <stdio.h>#include <algorithm>#include <math.h>#include <string.h>using namespace std;#define maxn 310000int top[maxn],tmp[maxn];int len;char rec[maxn];int rec1[maxn];int L[maxn];int sa[maxn];int rank[maxn],height[maxn];int *str;void makesa(){ int lena = len < 256 ? 256 : len; memset(top, 0, lena*sizeof(int)); for (int i = 0; i < len; i++) top[rank[i] = str[i]&(-1)]++; for (int i = 1; i < lena; i++) top[i] += top[i-1]; for (int i = 0; i < len ; i++) sa[--top[rank[i]]] = i; for (int k = 1; k < len; k <<= 1) { for (int i = 0; i < len; i++) { int j = sa[i]-k; if (j < 0) j += len; tmp[top[rank[j]]++] = j; } int j = sa[tmp[0]] = top[0] = 0; for (int i = 1; i < len; i++) { if (rank[tmp[i]] != rank[tmp[i-1]] || rank[tmp[i]+k] != rank[tmp[i-1]+k]) top[++j] = i; sa[tmp[i]] = j; } memcpy(rank, sa , len*sizeof(int)); memcpy(sa , tmp, len*sizeof(int)); if (j+1 >= len) break; }}void lcp(){ height[0] = 0; for (int i = 0, k = 0, j = rank[0]; i+1 < len; i++, k++) while (k >= 0 && str[i] != str[sa[j-1]+k]) { height[j] = k--; j = rank[sa[j]+1]; }}int main(){ int i,j,k=0; int left,right; int mid,number,ans,ans1,len_f; long long len_ab,len_b,l; int t; scanf("%d",&t); while(t--) { len_ab=len_b=0; scanf("%d",&number); scanf("%s",rec); for(len=0;rec[len];len++) { rec1[len]=rec[len]-'a'+1; } L[0]=len; for(i=1;i<=number;i++) { rec1[len++]=26+i; scanf("%s",rec); for(j=0;rec[j];j++) rec1[len++]=rec[j]-'a'+1; L[i]=j; } rec1[len++]=0; str=rec1; makesa(); lcp(); for ( i = 1; i < len; i++) len_ab += len-1-sa[i]-height[i]; l=len-1; for (i = 0; i < number; i++) { l -= L[i]; len_ab-= (L[i]+1)*l; l--; } len-=L[0]+1; str=rec1+L[0]+1; makesa(); lcp(); for(i = 1; i < len; i++) len_b += len-1-sa[i]-height[i]; l=len-1; for (i = 1; i < number; i++) { l -= L[i]; len_b-= (L[i]+1)*l; l--; } cout<<"Case "<<++k<<": "<<len_ab-len_b<<endl; } return 0;}