您的位置:首页 > 其它

BZOJ3620

2015-08-24 21:10 309 查看
传送门:BZOJ3620

暴力做法小练习。

本质上就是求一个串,又是前缀又是后缀,然后有各种奇奇怪怪的要求。

刚刚做了这种题……

枚举左端点i,枚举右端点j,对于[i,j],记录它们之间>k的最小的既是前缀又是后缀的值,判断这个值是否小于等于(j-i)/2即可。

数据给出来就是暴力的,O(n2)O(n^2)能过真是感人肺腑。

代码上的小细节见下。

[code]#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;

const int INF=0x7fffffff;

int pre[100005];
int num[100005];
char S[100005];
int len;
int c;

void Make_Table(char* S,int begin,int end)
{
    pre[begin]=begin-1;
    int k=begin-1;
    num[begin]=INF;
    for(int i=begin+1;i<=end;i++){
        while(k>=begin&&S[k+1]!=S[i])
            k=pre[k];
        if(S[k+1]==S[i])
            k++;
        pre[i]=k;
        num[i]=INF;
        if(k-begin+1>=c)
            num[i]=min(k-begin+1,num[pre[i]]);
    }
}

int Solve(int begin,int len)
{
    int ans=0;
    for(int i=begin+1;i<=len;i++)
        if((i-begin)/2>=num[i])
            ans++;
    return ans;
}

void Solve()
{
    int ans=0,len=strlen(S+1);
    for(int i=1;i<=len;i++){
        Make_Table(S,i,len);
        ans+=Solve(i,len);
    }
    printf("%d\n",ans);
}

void Close()
{
    fclose(stdin);
    fclose(stdout);
}

void Readdata()
{
    freopen("loli.in","r",stdin);
    scanf("%s",S+1);
    scanf("%d",&c);
}

int main()
{
    Readdata();
    Solve();
    Close();
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: