选拔赛之 kmp

自己稀里糊涂就过了,,原来是数据水。。但也还是不知道自己的代码其实能不能过,还是先放一下,,再看看能不能看得懂。。

id=97


对S串做个kmp得到fail数组,答案就是:

n = S.length();

while(fail[n] != -1) ans.push_back(S.length() - fail[n]), n = fail[n];

证明:由fail[n]可知,S[i] = S[i+S.length()-fail[n]] ( 0 <= i < fail[n] )其实就是满足了循环节为S.length()-fail[n]的定义。

很多人都是找了个循环串然后输出了个等差数列,这都是错的。比如下面的样例:

ababbababbaba

4

5 10 12 13

int ans[N], cnt;
int main() {
	while(~scanf("%s", s)) {
		int n = strlen(s);
		int j = -1, i = 0;
		f[0] = -1;
		while(i < n) {
			if( j < 0 || s[i] == s[j]) {
				++i, ++j;
				f[i] = j;
			}
			else j = f[j];
		}
		cnt = 0;
		i = n;
		while(f[i] != -1) {
			ans[cnt++] = n-f[i];
			i = f[i];
		}
		cout<<cnt<<endl;
		for(int i = 0; i < cnt; ++i)
			printf("%d%c", ans[i], i == cnt-1 ? '\n' : ' ');
	}
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值