列表

详情


NC217923. k-palindrome

描述

一个长度为的字符串被称为当前仅当以下条件满足:
1.对于.
2.若都是.
的本质不同的非空子串构成的集合。
对于,计算中有多少个
令当时的答案为
输出

输入描述

输入包含组测试用例,第一行一个整数
每组案例第一行两个整数
每组案例第二行一场长度为的字符串

输出描述

输出行第行一个整数表示第组测试用例的答案。

示例1

输入:

1
3 2
aba

输出:

10

说明:

{ans_1=3,ans_2=1},答案为{3*2^1+1*2^2=10}
{1-palindomre:a,b,aba}
{2-palindomre:aba}

原站题解

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

C++(clang++11) 解法, 执行用时: 11ms, 内存消耗: 1272K, 提交时间: 2021-05-14 19:32:08

#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;

typedef long long ll;

const int N = 5e5 + 100;
const int MOD = 998244353;

int n, m, tot;
int nex[N][26], fail[N], len[N], sa[N], dp[N], cnt[N];
char str[N];

void init() {
	for (int i = 0; i < tot; i++) {
		len[i] = fail[i] = 0;
		memset(nex[i], 0, sizeof(nex[i]));
	}
	fail[0] = 1; len[1] = -1; tot = 2;
}

int main() {
	//freopen("0.txt", "r", stdin);
	int T; scanf("%d", &T);
	while (T--) {
		scanf("%d%d%s", &n, &m, str + 1); init();
		for (int i = 1, p = 1; i <= n; i++) {
			int id = str[i] - 'a';
			while (str[i] != str[i - len[p] - 1]) p = fail[p];
			if (nex[p][id] == 0) {
				len[tot] = len[p] + 2;
				int v = fail[p];
				while (str[i] != str[i - len[v] - 1]) v = fail[v];
				fail[tot] = nex[v][id];
				nex[p][id] = tot++;
			}
			p = nex[p][id];
		}
		for (int i = 2; i < tot; i++) sa[i] = fail[i];
		for (int i = tot - 1; i > 1; i--) {
			if (len[i] == 1) continue;
			int p = fail[i];
			while (len[p] > len[i] / 2) p = fail[p];
			sa[i] = p;
			if (len[sa[fail[i]]] > len[sa[i]]) sa[fail[i]] = sa[i];
		}
		for (int i = 2; i < tot; i++) {
			if (len[i] == 1 || len[sa[i]] != len[i] / 2) dp[i] = 1;
			else dp[i] = dp[sa[i]] + 1;
			cnt[dp[i]]++;
		}
		for (int i = tot - 1; i >= 1; i--) cnt[i] += cnt[i + 1];
		ll ans = 0;
		for (int i = 1, j = 2; i <= m; i++, j = j * 2 % MOD) ans = (ans + 1LL * cnt[i] * j) % MOD;
		printf("%lld\n", ans);
		for (int i = 0; i <= tot + 5; i++) cnt[i] = 0;
	}
	return 0;
}

上一题