撸串

 

 

 

 

 

 

 

 

 直接考虑有几种情况

发现只能容错一次
那就好搞了

枚举循环节长度L


case 1:错误不在区间[1,L]中
那么循环节就是[1,L],直接hash判断是否后面是否相同,当遇到第一个不同时,就直接找出不同的删掉

case 2:错误在区间[1,L]中
那么循环节就一定是[L+1,L*2+1],和上面的一样判断
然后就没了。

主要就是枚举循环节长度L这个有点难想,一旦想到了那就简单了

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=200005;const int mod=1000000007;
int T,n;char s[N];ll hash[N],H[N];
inline ll read()
{
    char c=getchar();ll a=0,b=1;
    for(;c<'0'||c>'9';c=getchar())if(c=='-')b=-1;
    for(;c>='0'&&c<='9';c=getchar())a=a*10+c-48;
    return a*b;
}
inline void hash_pre()
{
    hash[0]=1;
    for(int i=1;i<=N-4;i++)
    {
        hash[i]=233*hash[i-1]%mod;
    }
}
inline int equal(int l,int r,int a,int b)
{
    return (((H[r]-H[l-1]*hash[r-l+1]%mod+mod)%mod)-(H[b]-H[a-1]*hash[b-a+1]%mod+mod)%mod)==0;
}
inline int miss(int l,int r,int a,int b)
{
    int L=0,R=b-a+1,ans;
    while(L<=R)
    {
        if(equal(l,l+((L+R)>>1)-1,a,a+((L+R)>>1)-1))
        {
            ans=((L+R)>>1);
            L=((L+R)>>1)+1;
        }
        else R=((L+R)>>1)-1;
    }
    return ans+1; 
}
int main()
{
    freopen("string.in","r",stdin);
    freopen("string.out","w",stdout);
    T=read();
    hash_pre();
    int i,j;
    while(T--)
    {
        n=read();
        scanf("%s",s+1);
        H[0]=0;
        if(n<2)
        {
            puts("0");
            break;
        }
        for(i=1;i<=n;i++)
        {
            H[i]=((H[i-1]*233)%mod+s[i])%mod;
        }
        for(i=1;i<n;i++)
        {
            if(i*2+1<=n)
            {
                int az=miss(1,i,i+2,i*2+1);
                if(az==n+1||(az<=n&&equal(az+1,i+1,i+1+az,i+i+1)))
                {
                    for(j=i*2+2;j<=n-i+1;j+=i)
                    {
                        if(equal(2+i,i+i+1,j,j+i-1)==false)break;
                    }
                    if(j+i-1>n&&equal(i+2,i+2+n-j,j,n))break;
                }
            }
            else
            {
                int az=miss(1,n-i-1,i+2,n);
                if(az==n-i)break;
                else 
                {
                    if(equal(az+1,n-i,i+az+1,n))break;
                }
            }
            for(j=i+1;j+i-1<=n;j+=i)
            {
                if(!equal(1,i,j,i+j-1))break;
            }
            if(j+i-1<=n)
            {
                int az=miss(1,i,j,i+j-1);
                if(j+i-1==n&&equal(az,i-1,j+az,n))break;
                else if(equal(az,i,j+az,j+i))
                {
                    for(j+=i+1;j+i-1<=n;j+=i)
                    {
                        if(!equal(1,i,j,i+j-1))break;
                    }
                    if(j>n||(j+i-1>n&&equal(1,n-j+1,j,n)))break;
                }
            }
            else
            {
                if(equal(1,n-j+1,j,n))break;
                else
                {
                    int az=miss(1,n-j+1,j,n);
                    if(equal(az,n-j,az+j,n))break;
                }
            }
        }
        cout<<i<<endl;
    }
    return 0;
}

 

posted @ 2020-08-20 20:12  HL_ZZP  阅读(161)  评论(0编辑  收藏  举报