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:
#include <iostream>#include <string.h>#include <stdio.h>#define maxn 200010#define Smaxn 26using 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 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;}