zoukankan      html  css  js  c++  java
  • 【HUD-5790】Prefix (主席树+tire)

    似乎是归队赛的最后一道题。

    由于当时以为是公共字串所以没写555555,其实是求公共前缀。

    做法是建立tire,把tire上的点编号看成是值,查询第l到第r个字符串的区间内不重复的值的个数。建立主席树维护即可

    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #define rep(i,l,r) for(int i=l;i<=r;i++)
    #define dow(i,l,r) for(int i=r;i>=l;i--)
    #define LL long long
    #define maxn 100100
    #define mm 100000
    #define maxm 8000000
    using namespace std;
    
    int lson[maxm],rson[maxm],size[maxm],root[maxn],num[maxn],n,m,toti,totr,tot,son[maxn][26],pre[maxn];
    char s[maxn];
    
    int more1()
    {
        ++toti;
        memset(son[toti],0,sizeof(son[toti]));
        return toti;
    }
    
    int more2()
    {
        ++totr;
        lson[totr]=0;
        rson[totr]=0;
        size[totr]=0;
        return totr;
    }
    
    void add(int &x,int old,int l,int r,int y,int z)
    {
        x=more2();
        lson[x]=lson[old];
        rson[x]=rson[old];
        size[x]=size[old]+z;
        if (l==r) return;
        int mid=(l+r)>>1;
        if (y<=mid) add(lson[x],lson[old],l,mid,y,z);
        else add(rson[x],rson[old],mid+1,r,y,z);
    }
    
    int ask(int x,int y,int l,int r)
    {
    //    printf("%d %d %d %d %d %d %d
    ",x,y,l,r,size[x],size[lson[x]],size[rson[x]]);
        if (!x) return 0;
        if (l==r) return size[x];
        int  mid=(l+r)>>1;
        if (y<=mid) return ask(lson[x],y,l,mid)+size[rson[x]];
        return ask(rson[x],y,mid+1,r);
    } 
    
    int main()
    {
        while (scanf("%d",&n)!=EOF) {
            memset(pre,0,sizeof(pre));
            toti=0;
            more1();
            totr=0;
            tot=1;
            rep(i,1,n) {
                scanf("%s",s);
                int len=strlen(s);
                int u=1;
                root[i]=root[i-1];
                rep(j,0,len-1) {
                //    printf("	%d
    ",u);
                    ++tot;
                    if (!j) num[i]=tot;
                    int k=s[j]-'a';
                    if (!son[u][k]) son[u][k]=more1();
                //    printf("	%d
    ",u);
                    add(root[i],root[i],1,mm,tot,1);
                    if (pre[son[u][k]]) {
            //            printf("		%d
    ",pre[son[u][k]]);
                        add(root[i],root[i],1,mm,pre[son[u][k]],-1);
                    }
                    pre[son[u][k]]=tot;
                    u=son[u][k];
            //        printf("	%d
    ",u);
                }
            //    printf("%d
    ",size[root[i]]);
            }
            scanf("%d",&m);
            int z=0;
            while (m--) {
                int j,k;
                scanf("%d %d",&j,&k);
                int l=min((j+z)%n+1,(k+z)%n+1),r=max((j+z)%n+1,(k+z)%n+1);
        //        printf("%d %d
    ",l,r);
                printf("%d
    ",z=ask(root[r],num[l],1,mm));
            }
        }
        return 0;
    }
     
    View Code
  • 相关阅读:
    C语言实验报告(二)
    C语言实验报告(一)
    Modbus通信
    clip_region_rel&clip_region
    字符分割时对粘连字符的处理方法
    Labview读取二维码
    LabVIEW访问Access数据库教程
    利用Halcon寻找出边缘突出的部分
    利用Halcon提取出器件的中心部分
    Halcon中对于Tuple数据类型的操作
  • 原文地址:https://www.cnblogs.com/Macaulish/p/6658291.html
Copyright © 2011-2022 走看看