zoukankan      html  css  js  c++  java
  • [CTSC2012]$cheat/$熟悉的文章

    >题目描述 > >阿米巴是小强的好朋友。 > >在小强眼中,阿米巴是一个作文成绩很高的文艺青年。为了获取考试作文的真谛,小强向阿米巴求教。阿米巴给小强展示了几篇作文,小强觉得这些文章怎么看怎么觉得熟悉,仿佛是 >某些范文拼拼凑凑而成的。小强不禁向阿米巴投去了疑惑的眼光,却发现阿米巴露出了一个狡黠的微笑。 > >为了有说服力地向阿米巴展示阿米巴的作文是多么让人觉得“眼熟”,小强想出了一个评定作文 “熟悉程度”的量化指标:$L_0$ .小强首先将作文转化成一个 $01$ 串。之后,小强搜集了各路名家的文章,同样分别转化成 $01$ 串后,整理出一个包含了 $M$ 个 $01$ 串的“ 标准作文库 ”。 > 小强认为:如果一个 $01$ 串长度不少于 $L$ 且在标准作文库中的某个串里出现过(即,它是标准作文库的某个串的一个连续子串),那么它是“ 熟悉 ”的。对于一篇作文(一个 $01$ 串)$A$,如果能够把 $A$ 分割成若干段子串,其中“ 熟悉 ” 的子串的 长度总和不少于 $A$ 总长度的 $90\%$,那么称 $A$ 是 “ 熟悉的文章 ”。 $L_0$ 是 能够让 $A $成为 “ 熟悉的文章 ” 的 所有 $L$ 的最大值 (如果不存在这样的 $L$,那么规定 $L_0=0$) >

    (SAM)(dp)爆切就很难受

    首先我们发现这个(L)显然有单调性,考虑二分

    (dp_i) 表示匹配到第 (i) 位的最大匹配长度,然后处理 (len_i) 表示第 (i) 位能匹配到的最长子串

    然后可以设计状态转移方程

    首先很显然的 (dp_i=dp_{i-1})

    然后考虑其他转移 (dp_i=minlimits_{i-len_i le jle i-mid}dp_j+i-j)

    这个 (dp)(O(n^2)) 的,考虑优化

    发现可选区间右端点单调,且每个 (dp) 之间的优劣不会改变,可以用单调队列优化

    复杂度(O(sum|T|log|T|))

    AC代码
    
    #include <bits/stdc++.h>
    #define ll long long
    #define cri const register int
    #define re register
    #define len(tt) t[tt].len
    #define c(xx,yy) t[xx].ch[yy]
    #define f(xx) t[xx].f
    using namespace std;
    struct node{
    	int ch[3],f,len;
    }t[2200010];
    int tot=1,rt,las,L[1200010],dp[1200010];
    inline void add(cri x){
    	int p=las,np=las=++tot;
    	len(np)=len(p)+1;
    	for(;p&&!c(p,x);p=f(p)) c(p,x)=np;
    	if(!p) f(np)=rt;
    	else{
    		int q=c(p,x);
    		if(len(q)==len(p)+1) f(np)=q;
    		else {
    			int nq=++tot;t[nq]=t[q];
    			len(nq)=len(p)+1;
    			f(np)=f(q)=nq;
    			for(;p&&c(p,x)==q;p=f(p)) c(p,x)=nq;
    		}
    	}
    }
    int LEN,que[1100010],n;
    char s[1100010];
    inline void match(){
    	int len=0,now=rt;
    	for(int i=1;i<=LEN;i++){
    		int in=s[i]-'0';
    		if(c(now,in)) now=c(now,in),len++;
    		else{
    			for(;now&&!c(now,in);now=f(now));
    			if(!now) now=rt,len=0;
    			else len=len(now)+1,now=c(now,in);
    		}
    		L[i]=len;
    	}
    }
    inline bool check(cri mid){
    	int now=rt,l=1,r=0;
    	for(int i=1;i=0.9L*LEN;
    }
    int main(){
    	int N,M;
    	scanf("%d%d",&N,&M);
    	for(int i=1;i<=M;i++){
    		rt=las=1;
    		scanf("%s",s+1);LEN=strlen(s+1);
    		for(int j=1;j<=LEN;j++) add(s[j]-'0');
    		add(2);
    	}
    	for(int i=1;i<=N;i++){
    		scanf("%s",s+1);LEN=strlen(s+1);
    		match();
    		int l=0,r=LEN;
    		while(l>1;
    			if(check(mid)) l=mid;
    			else r=mid-1;
    		}
    		printf("%d
    ",l);
    	}
    }
    
  • 相关阅读:
    node体验
    JS练习--prototype的一道题目
    JS的OOP--继承之prototype
    JS的OOP--new一个function背后的实际操作
    JS中new运算符的运算顺序
    thymeleaf 拼接字符串与变量
    spring jpa exists
    LocalDateTime json格式化
    格式化java8 LocalDateTime
    springboot定时任务
  • 原文地址:https://www.cnblogs.com/mikufun-hzoi-cpp/p/12098919.html
Copyright © 2011-2022 走看看