【JZOJ5272】【GDOI2018模拟】神奇的重复序列(DP,性质题)

87 篇文章 0 订阅

Description

这里写图片描述

Solution

如果两个串重叠的话,那么很明显这个串会是一个周期串(画个图就知道了)。
枚举两个串的左端点的间距k,那么根据周期串的性质,在%k相同的地方都是相同的,那么我们枚举k,然后在枚举第一个串的左端点,然后用一个指针j向右扫过去。如果要把%k相同的修改为相同的话,那么就是保留其中出现次数最多的字符。那么我们对于%k的位置要存储每个字符出现多少次还有出现最多的是什么,和出现次数为p的个数,这个可以方便修改,当i向右移的时候,假如最大值的个数变为了0,那么最大值也最多向左移一位。每次j都一道不能再移为止。
最后j-i+1-k就是答案

Code

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
const int maxn=3007;
int i,j,k,l,t,n,m,ans,p,kk;
char s[maxn];
int a[maxn],d[220][maxn],b[maxn],c[maxn],o,g[maxn][maxn];
int main(){
    freopen("repeat.in","r",stdin);
    freopen("repeat.out","w",stdout);
    scanf("%d",&kk);
    scanf("%s",s+1);n=strlen(s+1);fo(i,1,n)a[i]=s[i]-'a';
    fo(k,1,n){
        j=k-1;o=0;fo(i,1,j)g[i][0]++;
        fo(i,1,j){
            t=++d[a[i]][i];g[i][t]++;g[i][t-1]--;
            if(t>c[i])c[i]=t;else o++;
        }
        fo(i,1,n-k){
            while(j+1<=n){
                if(d[a[j+1]][(j+1)%k]+1<=c[(j+1)%k]&&o+1>kk)break;
                j++;t=++d[a[j]][j%k];g[j%k][t]++;g[j%k][t-1]--;
                if(t>c[j%k])c[j%k]=t;
                else o++;
            }
            t=--d[a[i]][i%k];g[i%k][t]++,g[i%k][t+1]--;
            if(!g[i%k][c[i%k]])c[i%k]--;else o--;
            ans=max(ans,j-i+1-k);
        }
        fo(i,1,j){
            g[i%k][d[a[i]][i%k]]=0;
            d[a[i]][i%k]=0;
            c[i%k]=0;
        }
    //  memset(d,0,sizeof(d));memset(g,0,sizeof(g));memset(c,0,sizeof(c));
    }
    printf("%d\n",ans);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值