题目分析:
建出后缀自动机,然后把A串用倍增定位到后缀自动机上,再把B串用倍增定位到后缀自动机上。
SAM上每个点上的A串根据长度从小到大排序,建点,依次连边。
再对于SAM上面每个点,连到儿子的边,同时连到儿子的最小A串的边。
对于m组关系,建立x连到y定位到的SAM上的点的边,同时连y所能匹配的到定位到的点上的最短字符串的边。
然后跑拓扑排序就行了。
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 const int maxn = 205000; 5 6 char str[maxn]; 7 int na,nb,len,m; 8 int la[maxn],ra[maxn],lb[maxn],rb[maxn]; 9 10 int lst=1,nxt[maxn<<1][27],fa[maxn<<1],num=1,maxlen[maxn<<1],st[maxn]; 11 int lk[maxn],bh[maxn],maxnum; 12 vector<pair<int,int> > g[maxn*6]; 13 vector<int> chain[maxn<<1]; 14 int in[maxn*6]; 15 long long dis[maxn*6]; 16 17 int RMQ[maxn<<1][20],nowmax; 18 19 void buildRMQ(){ 20 RMQ[1][0] = 1; 21 for(int i=2;i<=num;i++) RMQ[i][0] = fa[i]; 22 for(int k=1;(1<<k)<=num;k++){ 23 nowmax = k; 24 for(int i=1;i<=num;i++) RMQ[i][k] = RMQ[RMQ[i][k-1]][k-1]; 25 } 26 } 27 28 int findhhh(int spp,int len){ 29 for(int i=nowmax;i>=0;i--)if(maxlen[RMQ[spp][i]]>len) spp=RMQ[spp][i]; 30 return spp; 31 } 32 33 void init(){ 34 for(int i=1;i<=num;i++) for(int j=0;(1<<j)<=num;j++)RMQ[i][j] = 0; 35 for(int i=1;i<=num;i++){ 36 for(int j=0;j<26;j++)nxt[i][j] = 0; 37 fa[i] = 0; maxlen[i] = 0; 38 chain[i].clear(); 39 } 40 for(int i=0;i<=len;i++) st[i] = 0; 41 for(int i=1;i<=nb;i++)lk[i] = 0; 42 for(int i=1;i<=na;i++) bh[i] = 0; 43 for(int i=0;i<=maxnum+1;i++)g[i].clear(),in[i] = 0; 44 lst = 1; num = 1; maxnum = 0; 45 } 46 47 queue<int> que; 48 void topu(){ 49 int sz = 0; 50 for(int i=0;i<=maxnum+1;i++) dis[i] = -1e18; 51 for(int i=0;i<=maxnum+1;i++) 52 if(!in[i]) que.push(i),sz++; 53 dis[0] = 0; 54 while(!que.empty()){ 55 int zz = que.front(); que.pop(); 56 for(int i=0;i<g[zz].size();i++){ 57 int to = g[zz][i].first; in[to]--; 58 if(!in[to]) sz++,que.push(to); 59 dis[to] = max(dis[to],dis[zz]+g[zz][i].second); 60 } 61 } 62 if(sz != maxnum+2) puts("-1"); 63 else printf("%lld ",dis[maxnum+1]); 64 } 65 66 void addedge(int from,int to,int w){ 67 g[from].push_back(make_pair(to,w)); 68 in[to]++; 69 } 70 71 void ins(int now){ 72 int np = ++num,p=lst; maxlen[np] = maxlen[lst]+1; 73 st[len-now-1] = np; 74 for(;p&&!nxt[p][str[now]-'a'];p = fa[p]) nxt[p][str[now]-'a'] = np; 75 if(!p) fa[np] = 1; 76 else{ 77 int q = nxt[p][str[now]-'a']; 78 if(maxlen[q] == maxlen[p]+1) fa[np] = q; 79 else{ 80 int nq = ++num; maxlen[nq] = maxlen[p]+1; 81 for(int i=0;i<26;i++) nxt[nq][i] = nxt[q][i]; 82 fa[nq] = fa[q]; 83 fa[q] = nq; fa[np] = nq; 84 for(;p&&nxt[p][str[now]-'a']==q;p=fa[p])nxt[p][str[now]-'a']=nq; 85 } 86 } 87 lst = np; 88 } 89 90 void findpos(int now,int dt,int pp){ 91 if(chain[now].size() == 0) return; 92 int l = 0,r = chain[now].size()-1; 93 while(l < r){ 94 int mid = (l+r)/2; 95 if(ra[chain[now][mid]]-la[chain[now][mid]]>=pp) r = mid; 96 else l = mid+1; 97 } 98 l = chain[now][l]; 99 if(ra[l]-la[l]<pp) return; 100 addedge(bh[dt],bh[l],ra[dt]-la[dt]+1); 101 } 102 103 int cmp(int alpha,int beta){ 104 if(ra[alpha]-la[alpha] < ra[beta]-la[beta]) return 1; 105 else return 0; 106 } 107 108 void read(){ 109 scanf("%s",str); 110 len = strlen(str); 111 scanf("%d",&na); 112 for(int i=1;i<=na;i++) scanf("%d%d",&la[i],&ra[i]); 113 for(int i=1;i<=na;i++)la[i]=len-la[i],ra[i]=len-ra[i],swap(la[i],ra[i]); 114 scanf("%d",&nb); 115 for(int i=1;i<=nb;i++) scanf("%d%d",&lb[i],&rb[i]); 116 for(int i=1;i<=nb;i++)lb[i]=len-lb[i],rb[i]=len-rb[i],swap(lb[i],rb[i]); 117 for(int i=len-1;i>=0;i--) ins(i); 118 buildRMQ(); 119 for(int i=2;i<=num;i++){addedge(fa[i],i,0);} 120 121 for(int i=1;i<=na;i++){ 122 int ym = findhhh(st[ra[i]],ra[i]-la[i]); 123 chain[ym].push_back(i); 124 } 125 for(int i=1;i<=num;i++) sort(chain[i].begin(),chain[i].end(),cmp); 126 maxnum = num; 127 for(int i=1;i<=num;i++) 128 for(int j=0;j<chain[i].size();j++) bh[chain[i][j]] = ++maxnum; 129 130 for(int i=2;i<=num;i++) 131 if(chain[i].size())addedge(fa[i],bh[chain[i][0]],0); 132 for(int i=1;i<=num;i++){ 133 for(int j=0;j<(int)chain[i].size()-1;j++) 134 addedge(bh[chain[i][j]],bh[chain[i][j+1]],0); 135 } 136 for(int i=1;i<=na;i++) addedge(0,bh[i],0); 137 for(int i=1;i<=na;i++) addedge(bh[i],maxnum+1,ra[i]-la[i]+1); 138 139 for(int i=1;i<=nb;i++){ 140 int ym = findhhh(st[rb[i]],rb[i]-lb[i]); 141 lk[i] = ym; 142 } 143 scanf("%d",&m); 144 for(int i=1;i<=m;i++){ 145 int x,y; scanf("%d%d",&x,&y); 146 addedge(bh[x],lk[y],ra[x]-la[x]+1); 147 findpos(lk[y],x,rb[y]-lb[y]); 148 } 149 } 150 151 int main(){ 152 //freopen("1.in","r",stdin); 153 int Tmp; scanf("%d",&Tmp); 154 while(Tmp--){ 155 init(); 156 read(); 157 topu(); 158 } 159 return 0; 160 }