HDU-4416_题解 发表于 2019-11-10 | 分类于 题解 | 依次模拟最长公共子串的匹配过程,每到一个状态,标记最长不可用后缀的长度countAns。全部跑完后,树形dp更新祖先的countAns,因为祖先是后缀,长度小于子孙的匹配部分的子串也不可用了。最后累加可用部分的数量得到答案。 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138/* *powered by caibiCH2 *create at 2019-11-10 20:44:12 */#include <bits/stdc++.h>#define elif else if//#define max(x,y) ((x)>(y)?(x):(y))//#define min(x,y) ((x)<(y)?(x):(y))#define INF 0x3f3f3f3ftypedef long long ll;using namespace std;typedef unsigned pnt;const char ori='a',fin='z';const pnt csize=fin-ori+1;const int maxn=110000;struct SAM{ struct node{ ll len,countAns; pnt next[csize],fa; int cnt,firstpos; }data[maxn<<1]; pnt l; void init(){ memset(this,0,sizeof(*this)); } void build(const string&s){ pnt lst=0; data[0].fa=-1; for(int i=0;i<s.length();++i){ char c=s[i]-ori; data[++l].len=data[lst].len+1; pnt p=lst;lst=l;data[l].cnt=1;data[l].firstpos=data[l].len-1; for(;(~p)&&!data[p].next[c];p=data[p].fa)data[p].next[c]=l; if(!~p)data[l].fa=0; else{ pnt q=data[p].next[c]; if(data[q].len==data[p].len+1)data[l].fa=q; else{ data[++l]=data[q];data[l].cnt=0; data[l].len=data[p].len+1; data[q].fa=data[l-1].fa=l; for(;(~p)&&data[p].next[c]==q;p=data[p].fa)data[p].next[c]=l; } } }// buildCnt(); } pnt find(const string&s){ pnt now=0; for(pnt i=0;i<s.length();++i){ if(!data[now].next[s[i]-ori])return 0; now=data[now].next[s[i]-ori]; } return now; } void run(const string&s){ pnt now=0;ll maxlen=0; for(int i=0;i<s.size();i+=1){ while(now&&!data[now].next[s[i]-ori])now=data[now].fa,maxlen=data[now].len; now=data[now].next[s[i]-ori]; if(now){ ++maxlen; data[now].countAns=max(data[now].countAns,maxlen); } } } ll count(){ vector<int>a(l+1),b(l+1); for(int i=0;i<=l;i+=1)++a[data[i].len]; for(int i=1;i<=l;i+=1)a[i]+=a[i-1]; for(int i=0;i<=l;i+=1)b[--a[data[i].len]]=i; for(int i=l;i;--i){ data[data[b[i]].fa].countAns= max(data[b[i]].countAns,data[data[b[i]].fa].countAns); } ll ans=0; for(int i=1;i<=l;i+=1){ ans+=max(0ll,data[b[i]].len-max(data[data[b[i]].fa].len,data[b[i]].countAns)); } return ans; } // void buildCnt(){// vector<int>a(l+1),b(l+1);// for(int i=0;i<=l;i+=1)++a[data[i].len];// for(int i=1;i<=l;i+=1)a[i]+=a[i-1];// for(int i=0;i<=l;i+=1)b[--a[data[i].len]]=i;// // for(int i=l;i;--i){// data[data[b[i]].fa].cnt+=data[b[i]].cnt;// }// data[0].cnt=0;// } void print(){ cout<<"Next DAG:"<<endl; for(int i=0;i<=l;i+=1){ cout<<i<<":"; for(char c=0;c<csize;c+=1){ if(data[i].next[c])cout<<char(ori+c)<<":"<<data[i].next[c]<<' '; } cout<<endl; } cout<<"parent tree:"<<endl; for(int i=1;i<=l;i+=1){ cout<<i<<':'<<data[i].fa<<' '; } cout<<endl; cout<<"cnt:"<<endl; for(int i=1;i<=l;i+=1){ cout<<i<<':'<<data[i].cnt<<' '; } } }dag;int main (/*int argc, char const* argv[]*/){ std::ios::sync_with_stdio(false);// std::cin.tie(0); int T;cin>>T; for(int o=1;o<=T;o+=1){ dag.init(); int n;cin>>n;string s;cin>>s;dag.build(s); for(int i=1;i<=n;i+=1){ string t;cin>>t; dag.run(t); } cout<<"Case "<<o<<": "<<dag.count()<<'\n';// cout<<dag.check()<<'\n'; } return 0;}