zoukankan      html  css  js  c++  java
  • ICPC2018焦作 K. Counting Failures on a Trie

    题意:

    给出一个字典树

    给出一个字符串

    匹配的时候,如果在字典树上失配了,则回到根节点,从字符串的下一个位置开始匹配

    给出q个询问

    每次询问字符串区间[l,r],会在字典树上失配几次,最后停在字典树的哪个节点

    求出字典树上的所有前缀哈希值,并标记这个哈希值对应的字典树上的节点

    二分+上面的哈希值 求出以字符串的每个位置为起点,当失配的时候的下一次开始匹配的字符串位置

    然后利用倍增求出 以每个位置为起点,失配2^i次的时候下一次开始匹配的字符串位置

    对于每个查询[l,r],根据倍增的结果可以log的时间内求出失配次数

    [最后一次失配地下一次开始匹配的字符串位置,r] 这段哈希值对应的字典树节点就是最后停留的节点

    #include<map>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    //#include<ctime>
    
    #define N 100006
    
    using namespace std;
    
    const int mod=10000019;
    
    int m;
    char s[N];
    
    int tr[N][26],tot;
    int to[N][21];
    
    typedef unsigned long long ULL;
    
    //map<ULL,int>mp,th;
    int mp[mod],th[mod];
    ULL who[mod];
    ULL hh[N],bit[N];
    
    int bit2[21];
    
    int yy;
    ULL yyy;
    
    void push(ULL val,int x,int tim)
    {
        yy=val%mod;
        while(th[yy]==tim)
        {
            ++yy;
            if(yy==mod) yy=0;
        }
        mp[yy]=x;
        who[yy]=val;
        th[yy]=tim;
    }
    
    void dfs(int x,ULL val,int tim)
    {
        //mp[val]=x;
        //th[val]=tim;
        //mp[yy]=x;
        //th[yy]=tim;
        push(val,x,tim);
        for(int i=0;i<26;++i)
            if(tr[x][i]) dfs(tr[x][i],val*27+i+1,tim);
    }
    
    int check(int l,int r,int tim)
    {
        if(r>m || l>r) return 0;
        yyy=hh[r]-hh[l-1]*bit[r-l+1];
        yy=yyy%mod;
        if(th[yy]!=tim) return 0;
        while(th[yy]==tim)
        {
            if(who[yy]==yyy) return mp[yy];
            ++yy;
            if(yy==mod) yy=0; 
        }
        return 0;
    }
    
    int main()
    {
    //    freopen("data2.txt","r",stdin); 
    //    freopen("11.txt","w",stdout);
        int T,n,q,fi;
        int l,r,mid,tmp;
        int p;
        int sum;
        char ss[3];
        bit2[0]=1;
        for(int i=1;i<21;++i) bit2[i]=bit2[i-1]<<1;
        bit[0]=1;
        for(int i=1;i<N;++i) bit[i]=bit[i-1]*27;
        scanf("%d",&T);
        for(int t=1;t<=T;++t)
        {
            
            scanf("%d%d%d",&n,&m,&q);
            for(int i=1;i<=n;++i)
            {
                scanf("%d%s",&fi,ss);
                tr[fi][ss[0]-'a']=++tot;
            }
            scanf("%s",s+1);
            for(int i=1;i<=m;++i) hh[i]=hh[i-1]*27+(s[i]-'a'+1);    
        //    int t1=clock();    
            dfs(0,0,t);
        //    printf("%.3lf
    ",(clock()-t1)/1000.0);
        //    int t2=clock();
            for(int i=1;i<=m;++i)    
            {
                l=i;
                r=m+1;
                while(l<=r)
                {
                    mid=l+r>>1;
                    if(check(i,mid,t)) l=mid+1;
                    else 
                    {
                        tmp=mid;
                        r=mid-1;
                    }
                }
                to[i][0]=tmp+1;
            }
        //    printf("%.3lf
    ",(clock()-t2)/1000.0);
        //    int t3=clock();
            p=0;
            while(bit2[p]<m) ++p;
            for(int i=0;i<=p;++i) to[m+1][i]=to[m+2][i]=m+2;
            for(int i=1;i<=p;++i)
                for(int j=1;j<=m;++j)
                    to[j][i]=to[to[j][i-1]][i-1];
        //    printf("%.3lf
    ",(clock()-t3)/1000.0);
            while(q--)
            {
                scanf("%d%d",&l,&r);
                sum=0;
                for(int i=p;i>=0;--i)
                    if(l<=r && to[l][i]<=r+1) 
                    {
                        l=to[l][i];
                        sum+=bit2[i];
                    }
                check(l,r,t);
                printf("%d %d
    ",sum,check(l,r,t)); 
            }        
            for(int i=0;i<=tot;++i) memset(tr[i],0,sizeof(tr[i])); 
            tot=0;
        }
    }
  • 相关阅读:
    uC/OS II原理分析及源码阅读(一)
    并查集回顾
    js中ascii码的转换
    NS2中trace文件分析
    NS2中修改载波侦听范围和传输范围
    ubuntu wubi非在线快速安装
    用康托展开实现全排列(STL、itertools)
    日期的各种计算
    求约数的个数(约数个数定理)
    Parallel.js初探续集
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/14087291.html
Copyright © 2011-2022 走看看