Detection of Extraterrestrial KMP匹配 重复k次子串 好题

一开始以为这道题是后缀数组,想了好久没想明白怎么做,后来发现暴力枚举起点,进行KMP就好了。

枚举起点以后,构建fail数组。

遍历fail数组,如果串s[l,r]是由串s[s,t]重复k次得到的,那么fail数组的样子一定如下

index: [l] [l+1] [l+2] ....[t] [t+1] [t+2]....[r]

    fail: [0] [*]   [*]     ...[*] [1] [2] [3] ....[r-t]

并且(r-l+1)一定是(t-s+1)的倍数。

len = r-l+1

如果len > ans[k],记把ans数组k的位置更新成len。

这样的话我们在输出答案的时候,要输出重复t次的最长串长度,那么答案一定是ans[t],ans[2t]...ans[kt]里面的最大值

因为重复2t次也可以看作是重复t次,相邻的2个合成1个来看。

时间复杂度

O(n*n+n+nlogn)=O(n2)


#include <bits/stdc++.h> 
using namespace std;
#define MAXN 2000001
const int maxn = 1005;
char str[maxn];
char *s;
int fail[maxn];
int ans[maxn];
void make_fail()
{
  for (int i = 1, j = 0; s[i]; i++){
    while (j && s[i] != s[j])j = fail[j - 1];
    if (s[i] == s[j])fail[i] = ++j;
    else fail[i] = 0;
  }
}
int cas = 0;
void solve(){
	memset(ans,0,sizeof(ans));
	int len = strlen(str);
	int pre = -1;
	for(int i = 0;i < len;i++){
		s = str+i;
		make_fail();
		for(int j = 0;s[j];j++){
			if(fail[j] == pre + 1){
				pre++;
				if(pre >= 1 && (j+1)%(j+1-pre) == 0){
					ans[(j+1)/(j+1-pre)] = max(ans[(j+1)/(j+1-pre)],j+1);
				}
			}
			else if(fail[j] < pre){
				pre = 0;
			}
		}
	}
	/*
	for(int i = 0;i < len;++i){
		cout<<ans[i]<<endl;
	}
	*/
	printf("Case #%d: %d",++cas,len);
	for(int i = 2;i <= len;i++){
		int pt = 0;
		for(int j = i;j <= len;j += i){
			pt = max(pt,ans[j]);
		}
		printf(" %d",pt);
	}
	puts("");
}
int main(){
	int T = 1;
	cin>>T;
	while(T--){
		cin>>str;
		solve();
	}
	return 0;
} 




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值