[loj3049]字符串问题
考虑将所有A串向所能支配的B串连边,B串向满足B串是A串前缀的A串连边,在A串上有点权,跑最长路即可
但这样前缀的边太多,考虑优化:在后缀树上,将这些串插入进去(注意相同的串A串要在B串下面),并将父亲向儿子连边,那么相当于实现了上面的问题
但这样还有一个问题:需要将所有A串裂为两个点,因为并不是经过A串就一定可以有收益,而是要选择A串(即走A串连向B串的边)才有收益
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 1000005 4 #define oo 1e18 5 struct ji{ 6 int nex,to; 7 }edge[N]; 8 vector<pair<int,int> >v[N]; 9 int V,E,las,t,n,m,q,l,r,la[N],len[N],nex[N],ch[N][31],f[N][21],head[N],vis[N],val[N]; 10 long long ans,dp[N]; 11 char s[N]; 12 void add(int c){ 13 int p=las,np=las=++V; 14 len[V]=len[p]+1; 15 while ((p)&&(!ch[p][c])){ 16 ch[p][c]=las; 17 p=nex[p]; 18 } 19 if (!p)nex[las]=1; 20 else{ 21 int q=ch[p][c],nq=++V; 22 memcpy(ch[nq],ch[q],sizeof(ch[q])); 23 nex[nq]=nex[q]; 24 len[nq]=len[p]+1; 25 ch[p][c]=nex[q]=nex[las]=nq; 26 while ((p)&&(ch[p][c]==q)){ 27 ch[p][c]=nq; 28 p=nex[p]; 29 } 30 } 31 } 32 int query(int k,int l){ 33 for(int i=20;i>=0;i--) 34 if (len[f[k][i]]>=l)k=f[k][i]; 35 return k; 36 } 37 void add(int x,int y){ 38 edge[E].nex=head[x]; 39 edge[E].to=y; 40 head[x]=E++; 41 } 42 long long dfs(int k){ 43 if (vis[k])return oo; 44 if (dp[k]>=0)return dp[k]; 45 vis[k]=1; 46 long long ans=0; 47 for(int i=head[k];i!=-1;i=edge[i].nex)ans=max(ans,dfs(edge[i].to)); 48 dp[k]=ans+val[k]; 49 vis[k]=0; 50 return dp[k]; 51 } 52 int main(){ 53 scanf("%d",&t); 54 while (t--){ 55 scanf("%s",s); 56 int l=strlen(s); 57 las=V=1; 58 E=ans=0; 59 memset(head,-1,sizeof(head)); 60 memset(vis,0,sizeof(vis)); 61 memset(ch,0,sizeof(ch)); 62 memset(val,0,sizeof(val)); 63 memset(dp,-1,sizeof(dp)); 64 for(int i=l-1;i>=0;i--){ 65 add(s[i]-'a'); 66 la[i]=las; 67 } 68 for(int i=1;i<=V;i++)f[i][0]=nex[i]; 69 for(int i=1;i<=20;i++) 70 for(int j=1;j<=V;j++)f[j][i]=f[f[j][i-1]][i-1]; 71 for(int i=1;i<=V;i++){ 72 v[i].clear(); 73 v[i].push_back(make_pair(len[nex[i]],-nex[i])); 74 v[i].push_back(make_pair(len[i],-i)); 75 } 76 int VV=V; 77 scanf("%d",&n); 78 for(int i=1;i<=n;i++){ 79 scanf("%d%d",&l,&r); 80 int k=query(la[l-1],r-l+1); 81 val[++V]=r-l+1; 82 v[k].push_back(make_pair(r-l+1,-V)); 83 } 84 scanf("%d",&m); 85 for(int i=1;i<=m;i++){ 86 scanf("%d%d",&l,&r); 87 int k=query(la[l-1],r-l+1); 88 v[k].push_back(make_pair(r-l+1,-(++V))); 89 } 90 for(int i=1;i<=V-n-m;i++){ 91 sort(v[i].begin(),v[i].end()); 92 for(int j=0;j<v[i].size();j++){ 93 if (val[-v[i][j].second]){ 94 add(++V,-v[i][j].second); 95 v[i][j].second=-V; 96 } 97 if (j)add(-v[i][j-1].second,-v[i][j].second); 98 } 99 } 100 scanf("%d",&q); 101 for(int i=1;i<=q;i++){ 102 scanf("%d%d",&l,&r); 103 add(VV+l,VV+n+r); 104 } 105 for(int i=VV+n+m+1;i<=V;i++)ans=max(ans,dfs(i)); 106 if (ans>=oo)ans=-1; 107 printf("%lld\n",ans); 108 } 109 }