HDU 4763 拓展KMP

题意:给你一个串,问是否可以找到这样的三个串,是这个串的前缀,中间串, 后缀, 这个三个串相同,找出最长的这样的三个串。输出长度。

吐槽:昨天随手KMP就水过了,发现随便一组样例都过不了,数据真水。

思路:今天用拓展KMP做了一发,首先我们知道拓展KMP里面的next数组。假设next[i] = x 。(相对于这题,模式串和匹配串是一样的)

那么代表从位置i 起 共 x 个字符组成的子串, 和从首位置0起共 x 个字符组成的前缀子串相同。

那么对于这道题,我们首先求出了每个位置的next[i] 。

那么判断是否可以组成那样三个串,假设next[i] = x ,那么我们只需要比较 (l - x) - > l 这个位置上是否存在next[j] = (l - j)  .

然后注意三个串不能相交的情况。

数据比较水,我自己随机生成了100组长度为100W的数据,1.4s左右,目测写挫了。

#include <set>
#include <map>
#include <stack>
#include <cmath>
#include <queue>
#include <cstdio>
#include <string>
#include <vector>
#include <iomanip>
#include <cstring>
#include <iostream>
#include <algorithm>
#define Max 2505
#define FI first
#define SE second
#define ll long long
#define PI acos(-1.0)
#define inf 0x3fffffff
#define LL(x) ( x << 1 )
#define bug puts("here")
#define PII pair<int,int>
#define RR(x) ( x << 1 | 1 )
#define mp(a,b) make_pair(a,b)
#define mem(a,b) memset(a,b,sizeof(a))
#define REP(i,s,t) for( int i = ( s ) ; i <= ( t ) ; ++ i )

using namespace std;
#include <ctime>
#define N 1111111
char a[N] ;
char b[N] ;
int Next[N] ;
int R , C ;
map<string , int>M ;
int num = 0 ;
int ex[N] ;

void EX_Next(){
    int x = 0 ;
    int l = R ;
    Next[0] = l ;
    while(x < l - 1 && b[x] == b[x + 1])x ++ ;
    Next[1] = x ;
    x = 1 ;
    for (int k = 2 ; k < l ; k ++ ){
        int p = x + Next[x] - 1 , L = Next[k - x] ;
        if(k - 1 + L >= p){
            int j = (p - k + 1) > 0 ? (p - k + 1) : 0 ;
            while(k + j < l && b[k + j] == b[j]) j ++ ;
            Next[k] = j ;
            x = k ;
        }else {
            Next[k] = L ;
        }
    }
}

void solve(){
    scanf("%s",b) ;R = strlen(b) ;
    EX_Next() ;int ans = 0 ;
    for (int i = 0 ; i < R ; i ++ ){
        int now = Next[i] ;
        int maxlen = min(now , i) ;
        for (int j = maxlen ; j >= 0 ; j -- ){
            int x = R - j ;
            if(x >= i + j && Next[x] == j){
                ans = max(ans , j) ;
                break ;
            }
        }
    }
    printf("%d\n",ans) ;
}
int main() {
    double x = clock() ;
    freopen("D:\\in.txt","r",stdin) ;
    freopen("D:\\out.txt","w",stdout) ;
    int _ ; cin >> _ ; while(_ --) solve() ;
    double y = clock() ;
    cout << (y - x) / 1000 << endl ;
    return 0 ;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值