4673. 【NOIP2016提高A组模拟7.20】LCS again

版权声明:蒟蒻写的文章,能看就行了,同时欢迎大佬们指点错误 https://blog.csdn.net/Algor_pro_king_John/article/details/88921053

Problem

给定一个仅包含前 m m 个小写字符的字符串,允许改变其中一个字符,求可能有多少种不同的字符串。

Data constraint

n 1 0 6 n\le 10^6 m 26 m\le26

Solution

有点坑。。。

具体是分两大类讨论:

S i = S i 1 S_i=S_{i-1} S i S i 1 S_i\neq S_{i-1} 两种情况。

对于前者较为复杂,又分两小类,即 T i = S i + 1 T_i=S_{i+1} S i = T i + 1 S_i=T_{i+1} 两种情况

注意讨论 a b a b a b ababab 这样的情况以及交换相邻两个字符的情况

然后就有下面的代码:

#include <bits/stdc++.h>

#define F(i, a, b) for (int i = a; i <= b; i ++)

const int N = 1e5 + 10;

using namespace std;

long long Ans;
int n,m, sum, S[N], Up[N];
bool bz; char s[N];

int main() {
	scanf("%d%d", &n, &m);
	scanf("%s", s + 1);
	F(i, 2, n) S[i] = S[i - 1] + (s[i] != s[i - 1]);
	for (int i = 1, j; i <= n; i = j) {
		j = i + 2;
		while (s[j] == s[i])
			j += 2;
		for (int k = i; k < j; k += 2)
			Up[k] = j - 2;
	}
	for (int i = 2, j; i <= n; i = j) {
		j = i + 2;
		while (s[j] == s[i])
			j += 2;
		for (int k = i; k < j; k += 2)
			Up[k] = j - 2;
	}

	F(i, 1, n - 1)
		if (s[i] != s[i + 1]) {
			Ans ++; // 特殊情况,即交换S[i]与S[i+1]得到新序列 
			Ans += m - 2; // 仅仅改变S[i],对应的T[i]只有m-2种情况
			Ans += m - 2 + (s[i + 2] == s[i]) + (i + 2 == n + 1); //不能让T[i+1]==S[i]
			if (i + 3 <= n + 1 && s[i + 2] == s[i]) Ans --; // 特殊请况 
			// j==n+1 时没有S[i+1]的限制, 所以是加m
			if (i <= n - 2)
				Ans ++;
			Ans += (m - 1) * (n - i - 1);
			Ans += m - 2, bz = 1; // T[i]只有m-2种情况
			/*F(j, i + 2, n)
				if (s[j] != s[j - 1])
					Ans += m - 1;*/
			Ans += (S[n] - S[i + 1]) * (m - 1);
//			Ans -= max(Up[i], Up[i + 1]) - i - 1;
			/*int sum = 0;
			F(j, i + 2, n) {
				if (bz && s[j] == s[j - 2])
					sum ++;
				else
					bz = 0;
			}*/
			int w;
			if (Up[i] == Up[i + 1] + 1) w = Up[i] - i - 1; else
			if (Up[i + 1] == Up[i] + 1) w = Up[i + 1] - i - 1; else
			w = min(Up[i], Up[i + 1]) - i;
			Ans -= w;
		}
		else {
			Ans += m - 1;
			Ans += (S[n] - S[i + 1]) * (m - 1);
		}

	printf("%lld\n", Ans + m - 1);
}

当然还有很多别的方法。但自己的方法永远是最好的。

猜你喜欢

转载自blog.csdn.net/Algor_pro_king_John/article/details/88921053