zoukankan      html  css  js  c++  java
  • 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
    ",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
    ",ans[i]);
        }
        return 0;
    }
    

      

    #6031. 「雅礼集训 2017 Day1」字符串

    内存限制:256 MiB时间限制:1000 ms标准输入输出
    题目类型:传统评测方式:文本比较
     

    题目描述

    令 s 与 w为两字符串,定义:

    1. w[l, r]表示字符串 w 在区间 [l, r]中的子串;
    2. w 在 ss中出现的频率定义为w 在 s 中出现的次数;
    3. 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
  • 相关阅读:
    Buuctfweb[ACTF2020 新生赛]Include
    Buuctfweb[极客大挑战 2019]Knife
    Buuctfweb[极客大挑战 2019]Secret File
    Buuctfmiscningen
    Buuctfweb[GYCTF2020]Blacklist
    Buuctfmisczip伪加密
    Buuctfweb[GXYCTF2019]Ping Ping Ping
    Buuctfmisc镜子里面的世界
    Buuctfweb[ACTF2020 新生赛]Exec
    转换...
  • 原文地址:https://www.cnblogs.com/wang9897/p/10073418.html
Copyright © 2011-2022 走看看