zoukankan      html  css  js  c++  java
  • Luogu-4022 [CTSC2012]熟悉的文章

    广义后缀自动机+DP

    对于作文库建出广义后缀自动机,广义自动机就是在每次添加一个字符串之前把(last=0),然后正常添加就好了

    对于每个询问串,预处理出每个位置(i)能向前匹配的最长长度(pp[i])

    二分长度(L),对于位置(i),设往前匹配到(j),满足(i-pp[i]<=j<=i-L), 则中间新增的匹配长度为(i-j),前面的匹配长为(f[j]),则(f[i]=f[j]+i-j)

    因为(i)是每次(+1)的,(pp[i])每次有可能(+1),所以(i-pp[i])是单调不降的,可以用单调队列来维护(f[i]-i)的值

    #include<map>
    #include<queue>
    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int maxn=2e6+100;
    struct SAM{
        int son[maxn][2],len[maxn],fa[maxn],pp[maxn];
        int tot,last,m,st[maxn],l,r,f[maxn];
        SAM(){tot=last=0,fa[0]=-1;}
        void insert(int x){
            int p=last,np=++tot;
            len[np]=len[p]+1;
            while(~p&&!son[p][x])
                son[p][x]=np,p=fa[p];
            if(p==-1)
                fa[np]=0;
            else{
                int q=son[p][x];
                if(len[q]==len[p]+1)
                    fa[np]=q;
                else{
                    int nq=++tot;
                    memcpy(son[nq],son[q],sizeof(son[q]));
                    fa[nq]=fa[q];
                    len[nq]=len[p]+1;
                    fa[q]=fa[np]=nq;
                    while(~p&&son[p][x]==q)
                        son[p][x]=nq,p=fa[p];
                }
            } 
            last=np;
        }
        void getlen(char *s,int n){
            int x=0,cnt=0;
            for(int i=1;i<=n;i++){
                int v=s[i]-'0';
                while(~x&&son[x][v]==0)
                    x=fa[x];
                if(x==-1){
                    x=cnt=0;
                    pp[i]=0;
                    continue;
                }
                cnt=min(cnt,len[x])+1;
                x=son[x][v];
                pp[i]=cnt;
            }
        }
        bool check(char *s,int n,int L){
            st[0]=0,r=0,l=1,f[0]=0;
            for(int i=1;i<=n;i++){
                f[i]=f[i-1];
                if(i-L<0) continue;
                while(r>=l&&f[st[r]]-st[r]<=f[i-L]-i+L) r--;
                st[++r]=i-L;
                while(r>=l&&st[l]<i-pp[i]) l++;
                if(r>=l)
                f[i]=max(f[i],f[st[l]]+i-st[l]);
            }
            return 10*f[n]>=9*n;
        }
    }sam;
    int n,m;
    char s[maxn];
    int main(){
    //	freopen("4022.in","r",stdin);
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++){
            scanf("%s",s+1);
            int len=strlen(s+1);
            sam.m=max(sam.m,len);
            sam.last=0;
            for(int i=1;i<=len;i++) sam.insert(s[i]-'0');
        }
        while(n--){
            scanf("%s",s+1);
            int len=strlen(s+1);
            sam.getlen(s,len);
            int l=1,r=len+1,mid,ans;
            while(l<r){
                mid=l+r>>1;
                if(sam.check(s,len,mid))
                    l=mid+1,ans=mid;
                else
                    r=mid;
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
    
    
    
    
    
    
    
    
  • 相关阅读:
    nodeJS中的包
    NPM
    代码检查工具jshint和csslint
    javascript中Date对象的应用
    Collection包结构,与Collections的区别
    TreeMap、HashMap、LindedHashMap的区别
    HashMap和ConcurrentHashMap的区别,HashMap的底层源码
    HashMap和HashTable的区别
    Map、Set、List、Queue、Stack的特点与用法
    String、StringBuffer与StringBuilder的区别
  • 原文地址:https://www.cnblogs.com/nianheng/p/10066428.html
Copyright © 2011-2022 走看看