• HDU7015


    Description

    给出一个长度为(n)的字符串(s)和一个正整数(k)。定义两个长度相同且相差不超过(k)个字符的字符串是”k-matching“的,对于每个(iin[1,n-1]),求(s_{1..i})的子串和(s_{i+1..n})的子串有多少对是”k-matching“的。

    Solution

    反过来考虑每一对“k-matching”的子串对那些答案有贡献。首先搞出一个数组(f(i,j))​​​​​,记录(s_{i...})​​​​​和(s_{j...})​​​​​最远能匹配的长度,可以固定(j-i)​​再用two-pointers解决。那么对于每对(i,j)​,它对答案的贡献如下:

    i-1 i i+1 ... i+f-2 i+f-1 i+f ... j-1 j j+1
    (ans) 0 +1 +2 ... +f-1 +f +f +f +f 0 0
    差分 0 +1 +1 +1 +1 +1 0 0 0 -f 0
    再差分 0 +1 0 0 0 0 -1 0 0 -f +f

    于是其对再差分数组的影响是(O(1))的​,用(f(i,j))更新完再差分数组再求两遍前缀和即可。

    时间复杂度(O(n^2))

    Code

    //Another String
    #include <algorithm>
    #include <cstdio>
    using std::min;
    const int N=3e3+10;
    int n,k; char s[N];
    int f[N][N]; long long ans[N];
    int main()
    {
        int T; scanf("%d",&T);
        while(T--)
        {
        
        scanf("%d%d",&n,&k); scanf("%s",s+1);
        for(int d=1;d<=n;d++)
        {
            int len=0,cnt=0;
            for(int i=1;i+d<=n;i++)
            {
                int j=i+d;
                while(cnt<=k) cnt+=(s[i+len]!=s[j+len]),len++;
                f[i][j]=min(len-1,min(d,n-j+1));
                len--,cnt-=(s[i]!=s[j]);
            }
        }
        for(int i=1;i<=n;i++)
            for(int j=i+1;j<=n;j++)
            {
                int len=f[i][j];
                ans[i]++;
                ans[i+len]--;
                ans[j]-=len;
                ans[j+1]+=len;
            }
        for(int i=1;i<=n;i++) ans[i]+=ans[i-1];
        for(int i=1;i<=n;i++) ans[i]+=ans[i-1];
        for(int i=1;i<n;i++) printf("%lld
    ",ans[i]);
        
        for(int i=0;i<=n+2;i++) ans[i]=0; 
    
        }
        return 0;
    }
    

    Description

    给出一个长度为(n)的字符串(s)和一个正整数(k)。定义两个长度相同且相差不超过(k)个字符的字符串是”k-matching“的,对于每个(iin[1,n-1]),求(s_{1..i})的子串和(s_{i+1..n})的子串有多少对是”k-matching“的。

    Solution

    反过来考虑每一对“k-matching”的子串对那些答案有贡献。首先搞出一个数组(f(i,j))​​​​​,记录(s_{i...})​​​​​和(s_{j...})​​​​​最远能匹配的长度,可以固定(j-i)​​再用two-pointers解决。那么对于每对(i,j)​,它对答案的贡献如下:

    (i-1) (i) (i+1) ... (i+f-2) (i+f-1) (i+f) ... (j-1) (j) (j+1)
    (ans) 0 +1 +2 ... +f-1 +f +f +f +f 0 0
    差分 0 +1 +1 +1 +1 +1 0 0 0 -f 0
    再差分 0 +1 0 0 0 0 -1 0 0 -f +f

    于是其对再差分数组的影响是(O(1))的​,用(f(i,j))更新完再差分数组再求两遍前缀和即可。

    时间复杂度(O(n^2))

    Code

    //Another String
    #include <algorithm>
    #include <cstdio>
    using std::min;
    const int N=3e3+10;
    int n,k; char s[N];
    int f[N][N]; long long ans[N];
    int main()
    {
        int T; scanf("%d",&T);
        while(T--)
        {
        
        scanf("%d%d",&n,&k); scanf("%s",s+1);
        for(int d=1;d<=n;d++)
        {
            int len=0,cnt=0;
            for(int i=1;i+d<=n;i++)
            {
                int j=i+d;
                while(cnt<=k) cnt+=(s[i+len]!=s[j+len]),len++;
                f[i][j]=min(len-1,min(d,n-j+1));
                len--,cnt-=(s[i]!=s[j]);
            }
        }
        for(int i=1;i<=n;i++)
            for(int j=i+1;j<=n;j++)
            {
                int len=f[i][j];
                ans[i]++;
                ans[i+len]--;
                ans[j]-=len;
                ans[j+1]+=len;
            }
        for(int i=1;i<=n;i++) ans[i]+=ans[i-1];
        for(int i=1;i<=n;i++) ans[i]+=ans[i-1];
        for(int i=1;i<n;i++) printf("%lld
    ",ans[i]);
        
        for(int i=0;i<=n+2;i++) ans[i]=0; 
    
        }
        return 0;
    }
    
  • 相关阅读:
    spring-tool-suite-4下载安装及报错的解决办法
    CentOS 6.5使用yum快速搭建LAMP环境
    jquery省份城市选择器
    js 将json字符串转换为json对象的方法解析
    Spring MVC添加支持Http的delete、put请求!(HiddenHttpMethodFilter)
    Filebeat工作原理
    filebeat_config
    Docker设置http代理
    转-OWASP CSRFGuard使用细节
    转-JavaWeb三大组件之Listener监听器
  • 原文地址:https://www.cnblogs.com/VisJiao/p/15097659.html
Copyright © 2020-2023  润新知