• Luogu4022 CTSC2012熟悉的文章(广义后缀自动机+二分答案+动态规划+单调队列)


      对作文库中的串建出广义SAM,然后显然可以二分答案,二分之后考虑暴力dp,设f[i]为前i位最长匹配长度,显然有f[i]=max(f[i-1],f[j]+i-j) (i-j>=l&&j+1~i能在作文库中匹配)。在SAM上跑并记录匹配长度,单调队列优化dp即可。

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define N 2200010
    char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
    int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
    int read()
    {
    	int x=0,f=1;char c=getchar();
    	while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
    	while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    	return x*f;
    }
    int n,m,son[N][2],fail[N],len[N],f[N],q[N],cnt=1,last;
    char s[N];
    int ins(int c,int p)
    {
        if (son[p][c])
        {
            int q=son[p][c];
            if (len[p]+1==len[q]) return q;
            else
            {
                int y=++cnt;
                len[y]=len[p]+1;
                memcpy(son[y],son[q],sizeof(son[q]));
                fail[y]=fail[q],fail[q]=y;
                while (son[p][c]==q) son[p][c]=y,p=fail[p];
                return y;
            }
        }
        else
        {
            int x=++cnt;len[x]=len[p]+1;
            while (!son[p][c]&&p) son[p][c]=x,p=fail[p];
            if (!p) fail[x]=1;
            else
            {
                int q=son[p][c];
                if (len[p]+1==len[q]) fail[x]=q;
                else
                {
                    int y=++cnt;
                    len[y]=len[p]+1;
                    memcpy(son[y],son[q],sizeof(son[q]));
                    fail[y]=fail[q],fail[x]=fail[q]=y;
                    while (son[p][c]==q) son[p][c]=y,p=fail[p];
                }
            }
            return x;
        }
    }
    bool check(int k,int n)
    {
    	int x=1,l=0;int head=0,tail=0;
    	for (int i=1;i<=n;i++)
    	{
    		while (!son[x][s[i]-'0']&&x) x=fail[x],l=len[x];
    		if (!x) x=1,l=0;
    		else x=son[x][s[i]-'0'],l++;
    		f[i]=f[i-1];
    		if (i>=k)
    		{
    			while (head<=tail&&f[q[tail]]-q[tail]<=f[i-k]-(i-k)) tail--;
    			q[++tail]=i-k;
    		}
    		if (l>=k)
    		{
    			while (q[head]<i-l) head++;
    			f[i]=max(f[i],f[q[head]]-q[head]+i);
    		}
    	}
    	return f[n]*10>=n*9;
    }
    int main()
    {
    #ifndef ONLINE_JUDGE
    	freopen("a.in","r",stdin);
    	freopen("a.out","w",stdout);
    	const char LL[]="%I64d
    ";
    #else
    	const char LL[]="%lld
    ";
    #endif
    	n=read(),m=read();
    	for (int i=1;i<=m;i++)
    	{
    		scanf("%s",s+1);int _=strlen(s+1);last=1;
    		for (int i=1;i<=_;i++) last=ins(s[i]-'0',last);
    	}
    	for (int i=1;i<=n;i++)
    	{
    		scanf("%s",s+1);int _=strlen(s+1);
    		int l=1,r=_,ans=0;
    		while (l<=r)
    		{
    			int mid=l+r>>1;
    			if (check(mid,_)) ans=mid,l=mid+1;
    			else r=mid-1;
    		}
    		printf("%d
    ",ans);
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    java匿名对象
    Java面向对象详解
    Java语言基本语法
    Win7下JDK环境变量的设置
    LeetCode-Shortest Word Distance
    LeetCode-Count Complete Tree Nodes
    LeetCode-Palindrome Pairs
    LeetCode- Implement Trie (Prefix Tree)
    LeetCode-Lowest Common Ancestor of a Binary Tre
    LeetCode- Binary Tree Longest Consecutive Sequence
  • 原文地址:https://www.cnblogs.com/Gloid/p/10829238.html
Copyright © 2020-2023  润新知