Contest Hunter - IHHH

来源:互联网 发布:北师珠网络教学 编辑:程序博客网 时间:2024/05/21 09:42

题意:

给出n个字符串和m个询问;

每个询问有l,r和一个字符串;

查询[l,r]区间中的所有是询问字符串的子串的最大长度;

n<=100000,m<=100000,字符串总长度<=500000;

此题为CH【弱省胡策】 #1 T2;


题解:

一道好题,感觉正解说起来只是一句话但是真是很有道理。。

就是说:将询问拆成log个区间,对线段树每个结点建AC自动机分别处理;

这样每个询问都只询问了log个区间,每个字符串也只被log个结点覆盖;

时间复杂度O(nlogn*26),代码极其好写。。

实际上这样也就是处理区间问题的基本方法之一,拆分成log个区间来做,用线段树一样的分析来保证复杂度;

不要忘了取模哦XD


代码:


#include<queue>#include<vector>#include<stdio.h>#include<string.h>#include<algorithm>#define N 110000#define LEN 610000#define S 26#define lson l,mid,no<<1#define rson mid+1,r,no<<1|1#define vec vector<int>#define iter vec::iteratorusing namespace std;char buf1[LEN];char* str[N];char buf2[LEN];char* p[N];int L[N],R[N];int ans[N];vec query[N<<2];int next[LEN][S],fail[LEN],len[LEN],tot;queue<int>q;int newnode(){int ret=++tot;memset(next[ret],0,sizeof(int)*S);fail[ret]=len[ret]=0;return ret;}void init(){tot=0;newnode();}void Insert(char* s){int p=1,index,l=0;while(*s!='\0'){index=*s-'a';if(!next[p][index])next[p][index]=newnode();p=next[p][index];s++;l++;}len[p]=max(len[p],l);}void Build(){int x,i,temp,p;q.push(1);while(!q.empty()){x=q.front(),q.pop();for(i=0;i<S;i++){if(next[x][i]){p=next[x][i];temp=fail[x];while(temp&&next[temp][i]==0)temp=fail[temp];if(temp)fail[p]=next[temp][i],len[p]=max(len[fail[p]],len[p]);elsefail[p]=1;q.push(p);}else{temp=fail[x];while(temp&&next[temp][i]==0)temp=fail[temp];if(temp)next[x][i]=next[temp][i];elsenext[x][i]=1;}}}}int calc(char* s){int p=1,ret=0;while(*s!='\0'){p=next[p][*s-'a'];ret=max(ret,len[p]);s++;}return ret;}void update(int l,int r,int no,int st,int en,int val){if(st<=l&&r<=en)query[no].push_back(val);else{int mid=l+r>>1;if(en<=mid)update(lson,st,en,val);else if(st>mid)update(rson,st,en,val);elseupdate(lson,st,en,val),update(rson,st,en,val);}}void slove(int l,int r,int no){if(!query[no].empty()){init();for(int i=l;i<=r;i++)Insert(str[i]);Build();for(iter it=query[no].begin();it!=query[no].end();it++)ans[*it]=max(calc(p[*it]),ans[*it]);}if(l==r)return ;int mid=l+r>>1;slove(lson);slove(rson);}int main(){int n,m,i,j,k,x,y;scanf("%d%d",&n,&m);str[0]=buf1,p[0]=buf2;for(i=1;i<=n;i++){str[i]=str[i-1]+strlen(str[i-1])+1;scanf("%s",str[i]);}for(i=1;i<=m;i++){p[i]=p[i-1]+strlen(p[i-1])+1;scanf("%d%d%s",L+i,R+i,p[i]);update(1,n,1,L[i],R[i],i);}slove(1,n,1);for(i=1;i<=m;i++)printf("%d\n",ans[i]%998244353);//千万别忘了取模!!!! return 0;}



0 0
原创粉丝点击