HDU5069(AC自动机+线段树)
题意:http://acm.hdu.edu.cn/showproblem.php?pid=5069
给你n个串,m个询问:以b串的前缀和a串的后缀最长是多少。
思路:https://blog.csdn.net/gatevin/article/details/46123703
讲的很全面了。
1 #define IOS ios_base::sync_with_stdio(0); cin.tie(0); 2 #include <cstdio>//sprintf islower isupper 3 #include <cstdlib>//malloc exit strcat itoa system("cls") 4 #include <iostream>//pair 5 #include <fstream>//freopen("C:\\Users\\13606\\Desktop\\Input.txt","r",stdin); 6 #include <bitset> 7 //#include <map> 8 //#include<unordered_map> 9 #include <vector> 10 #include <stack> 11 #include <set> 12 #include <string.h>//strstr substr strcat 13 #include <string> 14 #include <time.h>// srand(((unsigned)time(NULL))); Seed n=rand()%10 - 0~9; 15 #include <cmath> 16 #include <deque> 17 #include <queue>//priority_queue<int, vector<int>, greater<int> > q;//less 18 #include <vector>//emplace_back 19 //#include <math.h> 20 #include <cassert> 21 #include <iomanip> 22 //#include <windows.h>//reverse(a,a+len);// ~ ! ~ ! floor 23 #include <algorithm>//sort + unique : sz=unique(b+1,b+n+1)-(b+1);+nth_element(first, nth, last, compare) 24 using namespace std;//next_permutation(a+1,a+1+n);//prev_permutation 25 //****************** 26 clock_t __START,__END; 27 double __TOTALTIME; 28 void _MS(){__START=clock();} 29 void _ME(){__END=clock();__TOTALTIME=(double)(__END-__START)/CLOCKS_PER_SEC;cout<<"Time: "<<__TOTALTIME<<" s"<<endl;} 30 //*********************** 31 #define rint register int 32 #define fo(a,b,c) for(rint a=b;a<=c;++a) 33 #define fr(a,b,c) for(rint a=b;a>=c;--a) 34 #define mem(a,b) memset(a,b,sizeof(a)) 35 #define pr printf 36 #define sc scanf 37 #define ls rt<<1 38 #define rs rt<<1|1 39 typedef pair<int,int> PII; 40 typedef vector<int> VI; 41 typedef unsigned long long ull; 42 typedef long long ll; 43 typedef double db; 44 const db E=2.718281828; 45 const db PI=acos(-1.0); 46 const ll INF=(1LL<<60); 47 const int inf=(1<<30); 48 const db ESP=1e-9; 49 const int mod=(int)1e9+7; 50 const int N=(int)2e5+10; 51 52 char s[N]; 53 int in_id[N]; 54 struct node 55 { 56 int l,r; 57 }P[N]; 58 59 ll max_[N<<2],add[N<<2]; 60 61 void up(int rt,int l,int r){ 62 max_[rt]=max(max_[ls],max_[rs]); 63 } 64 void dn(int rt){ 65 if(add[rt]!=0) 66 { 67 max_[ls]=max(max_[ls],add[rt]); 68 max_[rs]=max(max_[rs],add[rt]); 69 add[ls]=max(add[ls],add[rt]); 70 add[rs]=max(add[rs],add[rt]); 71 add[rt]=0; 72 } 73 } 74 void Build(int l,int r,int rt) 75 { 76 max_[rt]=0; 77 add[rt]=0; 78 if(l==r) 79 { 80 return; 81 } 82 int mid=(l+r)>>1; 83 84 Build(l,mid,rt<<1); 85 Build(mid+1,r,rt<<1|1); 86 up(rt,l,r); 87 } 88 ll query_dot(int pos,int l,int r,int rt) 89 { 90 if(l==r) 91 { 92 return max_[rt]; 93 } 94 95 int mid=(l+r)>>1; 96 dn(rt); 97 if(pos<=mid) 98 return query_dot(pos,l,mid,rt<<1); 99 else 100 return query_dot(pos,mid+1,r,rt<<1|1); 101 } 102 void update_qu(int L,int R,ll V,int l,int r,int rt) 103 { 104 if(L>R)return; 105 if(L<=l&&r<=R) 106 { 107 max_[rt]=max(max_[rt],V); 108 add[rt]=max(add[rt],V); 109 return; 110 } 111 112 int mid=(l+r)>>1; 113 dn(rt); 114 if(L<=mid) 115 update_qu(L,R,V,l,mid,rt<<1); 116 if(R>mid) 117 update_qu(L,R,V,mid+1,r,rt<<1|1); 118 up(rt,l,r); 119 } 120 //-----------------------线段树 121 //==================================================================== 122 class MAP 123 { 124 public: 125 struct EDGE 126 { 127 int to,next; 128 }edge[N]; 129 130 int tot; 131 int head[N]; 132 133 int dfn[N],DFN,SZ[N]; 134 void Init(int n) 135 { 136 tot=DFN=0; 137 for(int i=0;i<=n;++i) 138 head[i]=SZ[i]=dfn[i]=0; 139 } 140 void add(int from,int to) 141 { 142 ++tot; 143 edge[tot].to=to; 144 edge[tot].next=head[from]; 145 head[from]=tot; 146 } 147 int dfs(int u,int fa) 148 { 149 dfn[u]=++DFN; 150 SZ[dfn[u]]=1; 151 for(int i=head[u];i;i=edge[i].next) 152 { 153 int to=edge[i].to; 154 if(to!=fa) 155 SZ[dfn[u]]+=dfs(to,u); 156 } 157 return SZ[dfn[u]]; 158 } 159 }mp; 160 //==================================================================== 161 //------------------------AC 162 class ac_automaton//失配时,尽可能长得保留后缀以重新开始匹配. 163 { 164 public: 165 int tot; 166 int trie[N][27]; 167 int fail[N]; 168 //other 169 //-------------- 170 void Init(int n) 171 { 172 tot=0; 173 for(int i=0;i<=n;++i) 174 { 175 fail[i]=0; 176 for(int j=1;j<=26;++j) 177 trie[i][j]=0; 178 } 179 } 180 int Insert(int l,int r) 181 { 182 int rt=0; 183 for(int i=l;i<=r;++i) 184 { 185 int id=s[i]-'A'+1; 186 if(!trie[rt][id])trie[rt][id]=++tot; 187 rt=trie[rt][id]; 188 } 189 return rt; 190 } 191 void Getfail() 192 { 193 queue<int>q; 194 for(int i=1;i<=26;++i) 195 { 196 int id=trie[0][i]; 197 if(id) 198 { 199 fail[id]=0; 200 q.push(id); 201 } 202 } 203 while(!q.empty()) 204 { 205 int rt=q.front();q.pop(); 206 for(int i=1;i<=26;++i) 207 { 208 int id=trie[rt][i]; 209 if(id) 210 { 211 fail[id]=trie[fail[rt]][i]; 212 q.push(id); 213 } 214 else 215 trie[rt][i]=trie[fail[rt]][i]; 216 } 217 } 218 } 219 void Find(int l,int r,ll sgm) 220 { 221 int rt=0; 222 for(int i=l;i<=r;++i) 223 { 224 rt=trie[rt][s[i]-'A'+1]; 225 int pos=mp.dfn[rt]; 226 update_qu(pos,pos+mp.SZ[pos]-1,i-l+1+sgm,1,tot+1,1); 227 // for(int j=1;j<=tot+1;++j)check(j,1,tot+1,1); 228 // cout<<endl; 229 } 230 } 231 }AC; 232 233 struct GG 234 { 235 int id,to_a; 236 }; 237 vector<vector<GG> >G(N); 238 ll ans[N]; 239 int aa[N],bb[N]; 240 241 int main() 242 { 243 // freopen("C:\\Users\\13606\\Desktop\\Input.txt","r",stdin); 244 // freopen("C:\\Users\\13606\\Desktop\\1.txt","w",stdout); 245 int n,m; 246 while(~sc("%d%d",&n,&m)) 247 { 248 for(int i=1;i<=n;++i)G[i].clear(); 249 int len=0; 250 for(int i=1;i<=n;++i) 251 { 252 sc("%s",s+1+len); 253 P[i].l=1+len; 254 len+=strlen(s+1+len); 255 P[i].r=len; 256 } 257 AC.Init(len); 258 for(int i=1;i<=n;++i) 259 in_id[i]=AC.Insert(P[i].l,P[i].r); 260 AC.Getfail(); 261 int tot=AC.tot+1; 262 Build(1,tot,1); 263 264 for(int i=1;i<=m;++i) 265 { 266 int a,b; 267 sc("%d%d",&a,&b); 268 aa[i]=a,bb[i]=b; 269 G[b].push_back({i,a}); 270 } 271 mp.Init(tot); 272 for(int i=1;i<=AC.tot;i++) 273 { 274 mp.add(i,AC.fail[i]); 275 mp.add(AC.fail[i],i); 276 } 277 mp.dfs(0,-1); 278 ll sgm=-100000000; 279 for(int i=1;i<=n;++i) 280 { 281 sgm+=100000000; 282 AC.Find(P[i].l,P[i].r,sgm); 283 int sz=G[i].size(); 284 for(int j=0;j<sz;++j) 285 { 286 GG now=G[i][j]; 287 ans[now.id]=max(0LL,query_dot(mp.dfn[in_id[now.to_a]],1,tot,1)-sgm); 288 } 289 } 290 for(int i=1;i<=m;++i) 291 pr("%lld\n",ans[i]); 292 } 293 return 0; 294 } 295 296 /**************************************************************************************/