LOJ#6031. 「雅礼集训 2017 Day1」字符串
题解 注意 p*k=定值 那么我们对k进行分情况讨论
当k很小的时候 这时候询问次数会很多 我们考虑直接莫队处理出这次询问所对应子串区间 然后直接对应sam上的right集合即可
当k很大的时候 这时候询问次数会很少 我们暴力枚举每个区间是否属于这次询问 然后logn倍增查询即可
#include <algorithm> #include <iostream> #include <cstring> #include <cstdio> #include <vector> #include <stack> #include <queue> #include <cmath> #include <set> #include <map> #define mp make_pair #define pb push_back #define pii pair<int,int> #define link(x) for(edge *j=h[x];j;j=j->next) #define inc(i,l,r) for(int i=l;i<=r;i++) #define dec(i,r,l) for(int i=r;i>=l;i--) const int MAXN=2e5+10; const double eps=1e-8; #define ll long long using namespace std; struct edge{int t;edge*next;}e[MAXN],*h[MAXN],*o=e; void add(int x,int y){o->t=y;o->next=h[x];h[x]=o++;} ll read(){ ll x=0,f=1;char ch=getchar(); while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch))x=x*10+ch-'0',ch=getchar(); return x*f; } int n,m,q,k; char str[MAXN]; int cur,rt,cnt,fa[MAXN],dis[MAXN],ch[MAXN][26],sz[MAXN]; void built(int x){ int last=cur;cur=++cnt;dis[cur]=dis[last]+1;int p=last;sz[cur]=1; for(;p&&!ch[p][x];p=fa[p])ch[p][x]=cur; if(!p)fa[cur]=rt; else{ int q=ch[p][x]; if(dis[q]==dis[p]+1)fa[cur]=q; else{ int nt=++cnt;dis[nt]=dis[p]+1; memcpy(ch[nt],ch[q],sizeof(ch[q])); fa[nt]=fa[q];fa[q]=fa[cur]=nt; for(;ch[p][x]==q;p=fa[p])ch[p][x]=nt; } } } int f[MAXN][21],dep[MAXN]; void dfs(int x,int pre,int deep){ f[x][0]=pre;dep[x]=deep+1; inc(i,1,20)f[x][i]=f[f[x][i-1]][i-1]; link(x){ dfs(j->t,x,deep+1); sz[x]+=sz[j->t]; } } int calc(int x,int t){ int y=x; for(int i=20;i>=0;i--){ if(dis[f[y][i]]>=t)y=f[y][i]; } return sz[y]; } typedef struct node{ string s;int l,r,id; }node; node d[MAXN]; typedef struct Node{ int l,r,id; }Node; Node que[MAXN]; int P[MAXN],Sz; bool cmp(node aa,node bb){ if(P[aa.l]==P[bb.l])return aa.r<bb.r; else return P[aa.l]<P[bb.l]; } bool cmp1(Node aaa,Node bbb){ return aaa.r<bbb.r; } int num[405][405],Rt[MAXN],Len[MAXN]; ll ans[MAXN]; int main(){ ios::sync_with_stdio(false); cin>>n>>m>>q>>k; Sz=sqrt(m); inc(i,1,m)P[i]=(i-1)/Sz+1; int base=sqrt(q*k); cin>>str; cur=rt=cnt=1; inc(i,0,n-1)built(str[i]-'a'); inc(i,1,cnt)add(fa[i],i); dfs(rt,0,0); inc(i,1,m)cin>>que[i].l>>que[i].r,que[i].l++,que[i].r++,que[i].id=i; inc(i,1,q)cin>>d[i].s>>d[i].l>>d[i].r,d[i].l++,d[i].r++,d[i].id=i; if(k<=base){ sort(d+1,d+q+1,cmp); int L=1;int R=0; inc(i,1,q){ while(R<d[i].r){ R++;num[que[R].l][que[R].r]++; } while(R>d[i].r){ num[que[R].l][que[R].r]--;R--; } while(L>d[i].l){ L--; num[que[L].l][que[L].r]++; } while(L<d[i].l){ num[que[L].l][que[L].r]--;L++; } int temp=rt;int len1=0; for(int j=0;j<k;j++){ int t1=d[i].s[j]-'a'; if(ch[temp][t1])temp=ch[temp][t1],len1++; else{ int pp=temp; for(;pp&&!ch[pp][t1];pp=fa[pp]); if(!pp)temp=rt,len1=0;else temp=ch[pp][t1],len1=dis[pp]+1; } /*for(int w=j;w>=j-len1+1;w--){ if(!num[w+1][j+1])continue; ans[d[i].id]+=1ll*num[w+1][j+1]*calc(temp,j-w+1); }*/ int len2=len1;int ppp=temp; while(ppp!=rt){ for(int w=j-dis[fa[ppp]];w>=j-len2+1;w--)ans[d[i].id]+=1ll*num[w+1][j+1]*sz[ppp]; ppp=fa[ppp];len2=dis[ppp]; } } } inc(i,1,q)printf("%lld\n",ans[i]); return 0; } else{ sort(que+1,que+m+1,cmp1); int tot=0; inc(i,1,q)Rt[i]=rt,Len[i]=0; inc(i,1,m){ while(tot<k&&tot<que[i].r){ inc(j,1,q){ int t1=d[j].s[tot]-'a';int temp=Rt[j]; if(ch[temp][t1])Rt[j]=ch[temp][t1],Len[j]++; else{ int pp=temp; for(;pp&&!ch[pp][t1];pp=fa[pp]); if(!pp)Rt[j]=rt,Len[j]=0;else Rt[j]=ch[pp][t1],Len[j]=dis[pp]+1; } } tot++; } inc(j,1,q){ if(que[i].id>=d[j].l&&que[i].id<=d[j].r){ if(Len[j]<que[i].r-que[i].l+1)continue; ans[j]+=calc(Rt[j],que[i].r-que[i].l+1); } } } inc(i,1,q)printf("%lld\n",ans[i]); } return 0; }
#6031. 「雅礼集训 2017 Day1」字符串
内存限制:256 MiB时间限制:1000 ms标准输入输出
题目类型:传统评测方式:文本比较
题目描述
令 s 与 w为两字符串,定义:
- w[l, r]表示字符串 w 在区间 [l, r]中的子串;
- w 在 ss中出现的频率定义为w 在 s 中出现的次数;
- f(s, w, l, r) 表示 w[l, r] 在 s 中出现的频率。
现在给定串 s,m 个区间 [l, r]和长度k,你要回答 q 个询问,每个询问给你一个长度为 k 的字符串 w 和两个整数 a, b求:
输入格式
第一行四个整数 n, m, q, kn,m,q,k,nn 表示 ss 的长度。
接下来一行一个长为 ss 的字符串 ss。
接下来 mm 行,每行两个整数表示 l_i, r_ili,ri。
接下来 qq 行,每行一个字符串 ww,两个整数 a, ba,b。
输出格式
对于每个询问一行,输出答案。
样例
样例输入
8 5 3 3
abacdaba
0 2
1 2
0 0
2 2
1 2
dab 1 4
bac 2 3
eeb 1 3
样例输出
7
3
2