优美的回文串

题源:牛客网
https://www.nowcoder.com/questionTerminal/cf00949583604f8c9f3315fd64236a8c?from=zhnkw&toCommentId=6219448

题目描述:
牛牛在书上看到一种字符串叫做回文串,当一个字符串从左到右和从右到左读都是一样的,就称这个字符串为回文串。牛牛又从好朋友羊羊那里了解到一种被称为优美的回文串的字符串,考虑一个长度为N只包含大写字母的字符串,写出它所有长度为M的连续子串(包含所有可能的起始位置的子串,相同的子串也要计入),如果这个字符串至少有K个子串都是回文串,我们就叫这个字符串为优美的回文串。现在给出一个N,牛牛希望你能帮他计算出长度为N的字符串有多少个是优美的回文串(每个位置都可以是’A’~'Z’的一个。)

输入描述:
输入数据包括三个整数N, M, K(2 ≤ N ≤ 11, 2 ≤ M ≤ N, 0 ≤ K ≤ 11).

示例1
输入
2 2 1

输出
26 长度为2的字符串,它长度为2的子串只有它自身。长度为2的回文串有"AA",“BB”,“CC”…“ZZ”,一共26种。

解法:

首先,对于一个用了n个字母的字符串,通过替换可以替换出A(n,26)种和它模式相同的字符串。
可以这样理解:先从26个字母中挑选n个字母,即有C(n,26)种组合方式,再按字母第一次出现的顺序进行排序,就有C(n,26)*A(n,n) 种字符串。
接下来我们只需要找出一共有多少种模式符合要求,再乘以对应的数量,再相加即可得到答案。

#include
#include
using namespace std;

int N, M, K;
char str[11];
long long answer = 0;
long long type[12];//表示用了i个字母的排列方式有type[i]种

bool IsElegantPalideome()//判断某个字符串是否是优美回文串
{

	int subNum=0;//子串中是回文串的个数

	for (int i = 0; i < N - M + 1; i++)//有N-M+1个子串,i表示子串的个数
	{
		int flag = 1;
		for (int j = 0; j < M / 2; j++)
		{
			if (str[i + j] != str[i + M - 1 - j])
			{
				flag = 0;
				break;
			}
		}
		if(flag)
			subNum++;
	}
	if (subNum >= K)
		return true;
	else
		return false;
}

void dfs(int len, int num)//len表示待填充的字符个数,num表示已经使用了num个字母
{
	if (len == 0)//不需要再填充字符了
	{
		if (IsElegantPalideome())//这个字符串是优美回文串
		{
			answer += type[num];//这种模式符合要求,通过替换这种模式的字符串共有type[num]种
		}
		return;
	}
	else
	{
		for (int i = 0; i <= num; i++)
		{
			str[len - 1] = 'A' + i;//用i控制字母的变化
			if (i == num)//出现此前没有用到的字母
				dfs(len - 1, num + 1);//所用字符数+1;
			else
				dfs(len - 1, num);
		}
	}
}
int main()
{
	cin >> N >> M >> K;

	type[0] = 0, type[1] = 26;
	for (int i = 2; i < 12; i++)
	{
		type[i] = type[i - 1] * (27 - i);
	}
	dfs(N, 0);
	cout << answer;
}

参考:https://www.jianshu.com/p/69eecb769321

帮到你了就点个赞吧!

你可能感兴趣的:(C++)