• 【BZOJ2806】【CTSC2012】—熟悉的文章(二分答案+广义后缀自动机+单调队列优化dp)


    传送门

    考虑二分这样一个LL
    现在问题变成是否存在一种切分使得满足熟悉的占9090以上
    可以考虑dpdp
    f[i]f[i]表示前ii位最长的
    f[i]=maxj[imatch,il]f[j]+ijf[i]=max_{jin[i-match,i-l]}{f[j]+i-j}

    matchmatch是当前能匹配的最大长度
    这个可以用广义SamSam维护
    这个dpdp发现可以单调队列优化

    然后就做完了

    #include<bits/stdc++.h>
    using namespace std;
    const int RLEN=1<<20|1;
    inline char gc(){
        static char ibuf[RLEN],*ib,*ob;
        (ob==ib)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
        return (ob==ib)?EOF:*ib++;
    }
    #define gc getchar
    inline int read(){
        char ch=gc();
        int res=0,f=1;
        while(!isdigit(ch))f^=ch=='-',ch=gc();
        while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
        return f?res:-res;
    }
    #define ll long long
    #define re register
    #define pii pair<int,int>
    #define pic pair<int,char>
    #define fi first
    #define se second
    #define pb push_back
    #define cs const
    #define bg begin
    #define poly vector<int>
    template<class T>inline void chemx(T &a,T b){a<b?a=b:0;}
    template<class T>inline void chemn(T &a,T b){a>b?a=b:0;}
    cs int N=1100005;
    int n,m;
    namespace Sam{
    	cs int M=N<<1;
    	int nxt[M][2],fa[M],len[M],tot;
    	inline void init(){
    		tot=1;
    	}
    	inline int insert(int last,int c){
    		if(nxt[last][c]&&len[last]==len[nxt[last][c]]-1)return nxt[last][c];
    		int cur=++tot,p=last,fg=0;
    		len[cur]=len[p]+1;
    		for(;p&&!nxt[p][c];p=fa[p])nxt[p][c]=cur;
    		if(!p)fa[cur]=1;
    		else{
    			int q=nxt[p][c];
    			if(len[p]+1==len[q])fa[cur]=q;
    			else {
    				int clo=++tot;
    				if(len[cur]==len[p]+1)fg=1;
    				fa[clo]=fa[q],len[clo]=len[p]+1;
    				memcpy(nxt[clo],nxt[q],sizeof(nxt[q]));
    				for(;p&&nxt[p][c]==q;p=fa[p])nxt[p][c]=clo;
    				fa[cur]=fa[q]=clo;
    			}
    		}
    		return fg?tot:cur;
    	}
    	int f[N];
    	int q[N];
    	inline bool check(int l,char *s,int k){
    		memset(f,-1,sizeof(int)*(l+1));
    		f[0]=0;int mxlen=0,p=1,hd=1,tl=0;
    		for(int i=1;i<=l;i++){
    			int c=s[i]-'0';f[i]=f[i-1];
    			while(p&&!nxt[p][c])p=fa[p],mxlen=len[p];
    			if(!p)p=1,mxlen=0;
    			if(nxt[p][c]){
    				p=nxt[p][c],mxlen++;
    			}
    			if(i<k)continue;
    			while(hd<=tl&&f[q[tl]]-q[tl]<=f[i-k]-i+k)tl--;
    			q[++tl]=i-k;
    			while(hd<=tl&&q[hd]<i-mxlen)hd++;
    			if(hd<=tl)chemx(f[i],(f[q[hd]]+i-q[hd]));
    		}
    		return f[l]*10>=l*9;
    	}
    	inline int query(char *s){
    		int Len=strlen(s+1);
    		int l=0,r=Len,res=0;
    		while(l<=r){
    			int mid=(l+r)>>1;
    			if(check(Len,s,mid))l=mid+1,res=mid;
    			else r=mid-1;
    		}
    		return res;
    	}
    }
    namespace Trie{
    	int nxt[N][2],tot,pos[N];
    	inline int insert(int u,int c){
    		return nxt[u][c]?nxt[u][c]:(nxt[u][c]=++tot);
    	}	
    	queue<int> q;
    	inline void build(){
    		pos[0]=1;
    		q.push(0);
    		while(!q.empty()){
    			int u=q.front();q.pop();
    			for(int i=0;i<=1;i++){
    				int v=nxt[u][i];
    				if(v){
    					pos[v]=Sam::insert(pos[u],i);
    					q.push(v);
    				}
    			}
    		}
    	}
    }
    char s[N];
    int pos[N];
    int main(){
    	Sam::init();
    	m=read(),n=read();
    	for(int i=1;i<=n;i++){
    		scanf("%s",s+1);
    		for(int j=1,len=strlen(s+1);j<=len;j++)
    			pos[j]=Trie::insert(pos[j-1],s[j]-'0');
    	}
    	Trie::build();
    	for(int i=1;i<=m;i++){
    		scanf("%s",s+1);int tt;
    		cout<<Sam::query(s)<<'
    ';
    	}
    }
    
  • 相关阅读:
    oracle权限配置
    oracle锁表处理
    小组成员
    个人项目 Individual Project
    Java单元测试框架 JUnit
    MyEclipse的快捷键大全(超级实用,方便)
    vs2008 连接 vss2005 出现 analyze utility 错误的解决方法
    EXTJS gridpanel 动态设置表头
    IE8不能上网的问题
    一些事件的评论
  • 原文地址:https://www.cnblogs.com/stargazer-cyk/p/12328438.html
Copyright © 2020-2023  润新知