计蒜客习题 匹配格式

26 篇文章 0 订阅

emmmm搜到这题相信你们都有题目把?

题意也很简单

我们怎么处理?我们枚举长度

如何枚举?二分 二分以后啥时候让l=mid+1呢?

那么就是开头等于ex[0] 一定等于当时的mid 因为这个就是根据mid配的

中间找一下有没有等于mid的 屁股再找一下有没有等于mid的 记得一定不是最后len-mid

因为小的时候后面的屁股可能空

所以看代码吧

#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define dbg(x) cout<<#x<<" = "<< (x)<< endl
const int MAX_N = 1000024;
int Next[MAX_N],ex[MAX_N];
char str[MAX_N],restr[MAX_N];
void getnext(char *str){
    int i = 0,j,po,len= strlen(str);
    Next[0] = len;
    while(str[i]==str[i+1]&&i+1<len)
        i++;
    Next[1] = i;
    po = 1;
    for(i = 2;i<len;++i){
        if(Next[i-po]+i<Next[po]+po)
            Next[i] = Next[i-po];
        else {
            j=Next[po]+po-i;
            if(j<0) j = 0;
            while(i+j<len&&str[j]==str[j+i])
                j++;
            Next[i] = j;
            po = i;
        }
    }
}
void exkmp(char *s1,char *s2){
    int i = 0,j,po,len = strlen(s1),l2=strlen(s2);
    getnext(s2);
    while(s1[i]==s2[i]&&i<l2&&i<len)
        i++;
    ex[0] = i;
    po = 0;
    for(i=1;i<len;++i){
        if(Next[i-po]+i<ex[po]+po)
            ex[i] = Next[i-po];
        else {
            j = ex[po]+po-i;
            if(j<0) j =0;
            while(i+j<len&&j<l2&&s1[j+i]==s2[j])
                j++;
            ex[i] = j ;
            po = i;
        }
    }
}
int main(){
    scanf("%s",str);
    int len = strlen(str);
    int l= 1,r=2*len/3-1;
    int flag ;
    while(l<=r){
        flag = 0;
        int mid = (l+r)>>1;
        if(mid>len/3){
            r=mid-1;
            continue;
        }
        string s="";
        char p[MAX_N];
        for(int i=0;i<mid;i++)
            s+=str[i];
        s.copy(p,mid,0);
        *(p+mid)='\0';
        exkmp(str,p);
        for(int i=mid;i<=len-2*mid-1;i++) if(ex[i]==ex[0]) {
            for(int j=len-2*mid-1;j<len;j++){
            if(ex[j]==ex[0]){
             l=mid+1;
             flag = 1;
             break;
            }
            }
            if(flag) break;
        }
        if(!flag)
        r=mid-1;
        }
        printf("%d\n",l-1);
    return 0;
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值