zoukankan      html  css  js  c++  java
  • 【洛谷3426】[POI2005] SZA-Template(KMP)

    点此看题面

    • 有一个长度为(n)的文本串,求一个最小长度的模式串可以打印出这个文本串。
    • 打印是指文本串一个位置可以匹配多次,但每个位置至少要匹配一次。
    • (nle5 imes10^5)

    (KMP)+(DP)

    考虑到这个模式串必然是文本串的一个前缀,因此知道长度就可以推断出其内容。

    所以记录(f_i)表示打印出文本串前(i)个字符所需的最小长度模式串。

    实际上,这个模式串同时也必然是文本串的一个后缀,因此我们(KMP)求出(nxt)数组,那么(f_i)实际上只有两种可能的取值:(i)或者(f_{nxt[i]})

    显然(i>f_{nxt[i]}),因此我们只需验证(f_{nxt[i]})是否可行,那就是要判断是否存在(jin[i-f_{nxt[i]},i))满足(f_j=f_{nxt[i]}),这样一来就可以在(j)的基础上再匹配上一个(f_{nxt[i]})得到(i)

    由于我们是从左往右(DP)的,肯定满足(j<i),因此这等价于判断最大的满足(f_j=f_{nxt[i]})(j)是否大于等于(i-f_{nxt[i]})

    只需开个(g_x)维护一下满足(f_i=x)的最后出现的(i)即可。

    代码:(O(n))

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define N 500000
    using namespace std;
    int n,nxt[N+5],f[N+5],g[N+5];char s[N+5];
    int main()
    {
    	RI i,j,x;scanf("%s",s+1),n=strlen(s+1);
    	for(i=2,j=0;i<=n;s[j+1]==s[i]&&++j,nxt[i++]=j) W(j&&s[j+1]^s[i]) j=nxt[j];//KMP求nxt数组
    	for(i=1;i<=n;++i) x=f[nxt[i]],g[f[i]=g[x]>=i-x?x:i]=i;return printf("%d
    ",f[n]),0;//简单DP,只需检验f[nxt[i]]
    }
    
    败得义无反顾,弱得一无是处
  • 相关阅读:
    奇数阶魔方问题
    《DSP using MATLAB》示例9.3
    《DSP using MATLAB》示例9.2
    《DSP using MATLAB》示例9.1
    找个目标很重要
    《DSP using MATLAB》示例Example 8.30
    《DSP using MATLAB》示例Example 8.29
    《DSP using MATLAB》示例Example 8.28
    《DSP using MATLAB》示例Example 8.27
    《DSP using MATLAB》示例Example 8.26
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/Luogu3426.html
Copyright © 2011-2022 走看看