列表

详情


NC50324. OKR-Periods of Words

描述

串是有限个小写字符的序列,特别的,一个空序列也可以是一个串。一个串P是串A的前缀,当且仅当存在串B,使得A=PB。如果并且P不是一个空串,那么我们说P是A的一个proper前缀。
定义Q是A的周期,当且仅当Q是A的一个proper前缀并且A是QQ的前缀(不一定要是proper前缀)。比如串ababababab都是串abababa的周期。串A的最大周期就是它最长的一个周期或者是一个空串(当A没有周期的时候),比如说,ababab的最大周期是abab。串abc的最大周期是空串。
给出一个串,求出它所有前缀的最大周期长度之和。

输入描述

第一行一个整数k,表示串的长度。
接下来一行表示给出的串。

输出描述

输出一个整数表示它所有前缀的最大周期长度之和。

示例1

输入:

8
babababa

输出:

24

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 20ms, 内存消耗: 5268K, 提交时间: 2019-12-08 22:36:06

#include <bits/stdc++.h>
using namespace std;

int main() {
  ios_base::sync_with_stdio(false);
  int n; cin >> n;
  string S; cin >> S; S.append("#");
  vector<int> next(n+1, -1);
  for (int i = 0, j = -1; i < n; next[++i] = ++j) {
    while (j != -1 && S[i] != S[j]) j = next[j];
  }
  long long tot = 0;
  for (int i = 0; i < n; i++) {
    int j = i+1;
    while (next[next[j]] != -1) j = next[j];
    if (next[next[i+1]] != -1) next[i+1] = j;
    // cout << i << " " << j << endl;
    if (j != 0) tot += i + 1 - j;
  }
  cout << tot << endl;
}

C++11(clang++ 3.9) 解法, 执行用时: 15ms, 内存消耗: 8940K, 提交时间: 2020-03-05 13:11:17

#include<cstdio>
char str[1000010];
int next[1000010],cnt[1000010];
int main()
{
	int n,i=0,j=-1;
	long long ans=0;
	scanf("%d%s",&n,str);
	next[0]=-1;
	while(i<n)
	{
		while(~j&&str[j]!=str[i]) j=next[j];
		i++,j++,next[i]=j;
	}
	for(i=1;i<=n;i++)
	{
		if(next[i]!=0) cnt[i]=cnt[next[i]];
		else cnt[i]=i;
		ans+=i-cnt[i];
	}
	printf("%lld\n",ans);
	return 0;
}

上一题