10pts 在线等, 求调 回必关
查看原帖
10pts 在线等, 求调 回必关
1050426
lxy_qwq楼主2025/7/22 16:39
思路:
枚举中心点, 然后把字符串分为左右两个部分
然后跑最长公共子序列, 得到的最长公共子序列就是左右两边的字符串共同拥有的部分, 剩下的部分需靠操作添加
#include <iostream>
#include <algorithm>
#include <map>
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1e5 + 5;
int result;
int main()
{
	result = INT_MAX;
	string s;
	cin >> s;
	//暴力找割点
	for (int i = 1; i < s.size() - 1; i++) {
		//以i为割点,分割两边, 然后跑最长公共子序列
		//
		string left = s.substr(0, i);
		string right = s.substr(i + 1, s.size());
		reverse(right.begin(), right.end());
		//cout << left << ' ' << right << endl;
		int len = max(left.size(), right.size());
		int a[len + 1];
		int b[len + 1];
		int r[len + 1];
		int c[len + 1];
		map<int, int> mp;
		int cnt = 0, pos = 0;
		for (int i = 0; i < left.size(); i++) {
			a[i + 1] = int(left[i]);
		}
		int xb = -1;
		for (int i = left.size() + 1; i <= len; i++) {
			a[i] = xb;
			xb--;
		}
		for (int i = 0; i < right.size(); i++) {
			b[i + 1] = int(right[i]);
		}
		for (int i = right.size() + 1; i <= len; i++) {
			b[i] = xb;
			xb--;
		}

		r[0] = 0;
		for (int i = 1; i <= len; i++) {
			//cout << i << " a[i]:" << a[i] << endl;
			mp[a[i]] = i;
			r[i] = 0;
		}
		for (int i = 1; i <= len; i++) {
			c[i] = mp[b[i]];
			//cout << mp[b[i]] << " b[i]:" << b[i] << endl;
		}


		for (int i = 1; i <= len; i++)
		{
			if (a[i] < 0 or b[i] < 0) {
				continue;
			}
			//cout << c[i] << ' ' << r[cnt] << endl;		
			if (c[i] >= r[cnt])
			{
				r[++cnt] = c[i];
			}
			else
			{
				pos = lower_bound(r + 1, r + 1 + cnt, c[i]) - r;
				r[pos] = c[i];
			}
		}
		//cout << cnt << endl;
		result = min(result, int(left.size() + right.size() - 2 * cnt));
	}
	
	for (int i = 1; i < s.size() - 2; i++) {
		//以i为割点,分割两边, 然后跑最长公共子序列
		//
		string left = s.substr(0, i);
		string right = s.substr(i + 2, s.size());
		reverse(right.begin(), right.end());
		//cout << left << ' ' << right << endl;
		int len = max(left.size(), right.size());
		int a[len + 1];
		int b[len + 1];
		int r[len + 1];
		int c[len + 1];
		map<int, int> mp;
		int cnt = 0, pos = 0;
		for (int i = 0; i < left.size(); i++) {
			a[i + 1] = int(left[i]);
		}
		int xb = -1;
		for (int i = left.size() + 1; i <= len; i++) {
			a[i] = xb;
			xb--;
		}
		for (int i = 0; i < right.size(); i++) {
			b[i + 1] = int(right[i]);
		}
		for (int i = right.size() + 1; i <= len; i++) {
			b[i] = xb;
			xb--;
		}

		r[0] = 0;
		for (int i = 1; i <= len; i++) {
			//cout << i << " a[i]:" << a[i] << endl;
			mp[a[i]] = i;
			r[i] = 0;
		}
		for (int i = 1; i <= len; i++) {
			c[i] = mp[b[i]];
			//cout << mp[b[i]] << " b[i]:" << b[i] << endl;
		}


		for (int i = 1; i <= len; i++)
		{
			if (a[i] < 0 or b[i] < 0) {
				continue;
			}
			//cout << c[i] << ' ' << r[cnt] << endl;		
			if (c[i] >= r[cnt])
			{
				r[++cnt] = c[i];
			}
			else
			{
				pos = lower_bound(r + 1, r + 1 + cnt, c[i]) - r;
				r[pos] = c[i];
			}
		}
		//cout << cnt << endl;
		result = min(result, int(left.size() + right.size() - 2 * cnt));
	}
	cout << result << endl;
	return 0;
}
2025/7/22 16:39
加载中...