In the 2012 Hangzhou network competition, the suffix of the array Suffix of the machine can be used.
Give a string S and a series of strings T1 ~ Tn: How many different substrings are there in S to meet the requirement that it is not T1 ~ The substring of any string in Tn.
Train of Thought: We first construct the suffix automatic mechanism of S, and then match each Ti on the sam of S. Similar to LCS, every State in S records a variable deep, representing T1 ~ Tn: What is the maximum length that can be matched in this state? After each Ti is matched, we sort the s sam topology and update the deep state from the bottom up, calculate the number of substrings in this status to meet the question requirements. The procedure is as follows:
1: if the current status is set to p and the par of p is set to q, the greater limit in q-> deep is updated to q-> deep and p-> deep.
2: If p-> deep <p-> val, it indicates that the length of p-> deep + 1 ~ is in p state ~ The substring of p-> val is not T1 ~ The substring of any string in Tn, so the answer is added with p-> val-p-> deep. Otherwise, all strings in status p do not meet the requirements. skip this step.
(Note if p-> deep = 0, it means all the substrings in State p meet the requirements of the question, but the answer is not to add p-> val-0, add p-> val-p-> par-> val, which indicates the number of strings in the p state. Therefore, special processing is required for p-> deep = 0)
Finally, output the answer.
The Code is as follows:
[Cpp]
# Include <iostream>
# Include <string. h>
# Include <stdio. h>
# Define maxn200010
# Define Smaxn 26
Using namespace std;
Struct node
{
Node * par, * go [Smaxn];
Int deep;
Int val;
} * Root, * tail, que [maxn], * top [maxn];
Int tot;
Char str [maxn> 1];
Void add (int c, int l)
{
Node * p = tail, * np = & que [tot ++];
Np-> val = l;
While (p & p-> go [c] = NULL)
P-> go [c] = np, p = p-> par;
If (p = NULL) np-> par = root;
Else
{
Node * q = p-> go [c];
If (p-> val + 1 = q-> val) np-> par = q;
Else
{
Node * nq = & que [tot ++];
* Nq = * q;
Nq-> val = p-> val + 1;
Np-> par = q-> par = nq;
While (p & p-> go [c] = q) p-> go [c] = nq, p = p-> par;
}
}
Tail = np;
}
Int c [maxn], len;
Void init (int n)
{
Int I;
For (I = 0; I <= n; I ++)
{
Que [I]. deep = que [I]. val = 0;
Que [I]. par = NULL;
Memset (que [I]. go, 0, sizeof (que [I]. go ));
}
Tot = 0;
Len = 1;
Root = tail = & que [tot ++];
}
Int max (int a, int B)
{
Return a> B? A: B;
}
Void solve (int q)
{
Memset (c, 0, sizeof (c ));
Int I;
For (I = 0; I <tot; I ++)
C [que [I]. val] ++;
For (I = 1; I <len; I ++)
C [I] + = c [I-1];
For (I = 0; I <tot; I ++)
Top [-- c [que [I]. val] = & que [I];
While (q --)
{
Node * p = root;
Scanf ("% s", str );
Int l = strlen (str), tmp = 0;
For (I = 0; I <l; I ++)
{
Int x = str [I]-'A ';
If (p-> go [x])
{
Tmp ++;
P = p-> go [x];
P-> deep = max (p-> deep, tmp );
}
Else
{
While (p & p-> go [x] = 0)
{
P = p-> par;
}
If (p)
{
Tmp = p-> val + 1;
P = p-> go [x];
P-> deep = max (tmp, p-> deep );
}
Else
{
Tmp = 0;
P = root;
}
}
}
}
Long sum = 0;
For (I = tot-1; I> 0; I --)
{
Node * q = top [I];
If (q-> deep> 0)
{
Q-> par-> deep = max (q-> par-> deep, q-> deep );
If (q-> deep <q-> val)
{
Sum + = q-> val-q-> deep;
}
}
Else
{
Sum + = q-> val-q-> par-> val;
}
}
Printf ("% I64d \ n", sum );
}
Int main ()
{
Freopen ("dd.txt", "r", stdin );
Int ncase, time = 0;
Scanf ("% d", & ncase );
While (ncase --)
{
Printf ("Case % d:", ++ time );
Int n;
Scanf ("% d", & n );
Scanf ("% s", str );
Int I, l = strlen (str );
Init (l * 2 );
For (I = 0; I <l; I ++)
Add (str [I]-'A', len ++ );
Solve (n );
}
Return 0;
}
# Include <iostream>
# Include <string. h>
# Include <stdio. h>
# Define maxn200010
# Define Smaxn 26
Using namespace std;
Struct node
{
Node * par, * go [Smaxn];
Int deep;
Int val;
} * Root, * tail, que [maxn], * top [maxn];
Int tot;
Char str [maxn> 1];
Void add (int c, int l)
{
Node * p = tail, * np = & que [tot ++];
Np-> val = l;
While (p & p-> go [c] = NULL)
P-> go [c] = np, p = p-> par;
If (p = NULL) np-> par = root;
Else
{
Node * q = p-> go [c];
If (p-> val + 1 = q-> val) np-> par = q;
Else
{
Node * nq = & que [tot ++];
* Nq = * q;
Nq-> val = p-> val + 1;
Np-> par = q-> par = nq;
While (p & p-> go [c] = q) p-> go [c] = nq, p = p-> par;
}
}
Tail = np;
}
Int c [maxn], len;
Void init (int n)
{
Int I;
For (I = 0; I <= n; I ++)
{
Que [I]. deep = que [I]. val = 0;
Que [I]. par = NULL;
Memset (que [I]. go, 0, sizeof (que [I]. go ));
}
Tot = 0;
Len = 1;
Root = tail = & que [tot ++];
}
Int max (int a, int B)
{
Return a> B? A: B;
}
Void solve (int q)
{
Memset (c, 0, sizeof (c ));
Int I;
For (I = 0; I <tot; I ++)
C [que [I]. val] ++;
For (I = 1; I <len; I ++)
C [I] + = c [I-1];
For (I = 0; I <tot; I ++)
Top [-- c [que [I]. val] = & que [I];
While (q --)
{
Node * p = root;
Scanf ("% s", str );
Int l = strlen (str), tmp = 0;
For (I = 0; I <l; I ++)
{
Int x = str [I]-'A ';
If (p-> go [x])
{
Tmp ++;
P = p-> go [x];
P-> deep = max (p-> deep, tmp );
}
Else
{
While (p & p-> go [x] = 0)
{
P = p-> par;
}
If (p)
{
Tmp = p-> val + 1;
P = p-> go [x];
P-> deep = max (tmp, p-> deep );
}
Else
{
Tmp = 0;
P = root;
}
}
}
}
Long sum = 0;
For (I = tot-1; I> 0; I --)
{
Node * q = top [I];
If (q-> deep> 0)
{
Q-> par-> deep = max (q-> par-> deep, q-> deep );
If (q-> deep <q-> val)
{
Sum + = q-> val-q-> deep;
}
}
Else
{
Sum + = q-> val-q-> par-> val;
}
}
Printf ("% I64d \ n", sum );
}
Int main ()
{
Freopen ("dd.txt", "r", stdin );
Int ncase, time = 0;
Scanf ("% d", & ncase );
While (ncase --)
{
Printf ("Case % d:", ++ time );
Int n;
Scanf ("% d", & n );
Scanf ("% s", str );
Int I, l = strlen (str );
Init (l * 2 );
For (I = 0; I <l; I ++)
Add (str [I]-'A', len ++ );
Solve (n );
}
Return 0;
}