C. Good String(规律,连通块)

这题不难啊,别被吓到了.

a 观察一下一个串a想要左移相等和右移相等需要满足什么条件。

i , i + 1 , i 1 显然如果移动后i位置相等,那么左移前是i+1,右移前是i-1

a i 1 = = a i + 1 , a i = = a i 2 即a_{i-1}==a_{i+1},也可以写成a_i==a_{i-2}

, a 1 = = a n 1 , a 2 = = a n 特别的,a_1==a_{n-1},a_2==a_n

a i = = a i 2 , 不难发现a_i==a_{i-2}这个式子,每隔两个单词就要相等

, , 所以如果串是偶数长度,那么所有奇数位置要相等,偶数位置也要相等

(如果你不是一眼能看出来,在纸上画一画n=8的情况,就是分奇数和偶数两个连通块)

, n = 7 \color{Red}如果串是奇数,假设n=7

a 1 = = a 6 , a 2 = = a 7 , a 3 = = a 1 , a 4 = = a 2 , a 5 = = a 3 那么a_1==a_6,a_2==a_7,a_3==a_1,a_4==a_2,a_5==a_3

a 6 = = a 4 , a 7 = = a 5 a_6==a_4,a_7==a_5

可以发现这7个字母构成一个连通块,7个字母全部都要相等

算法就很显然了

, 先假定满足条件的最长串是奇数,找出现次数最多的那个字母即可

, , 若最长串是偶数,枚举奇数位置和偶数位置应该放的字母,然后去找最长串

找到最长串后,要删掉的字母就是原长度-符合要求的最长序列

#include <bits/stdc++.h>
using namespace std;
int t,vis[11];
char a[200009];
int run(int q,int w,int n)
{
	char qq=q+'0',ww=w+'0';
	int ok=0,temp=0;
	for(int i=1;i<=n;i++)
	{
		if( a[i]==qq&&ok==0 )	ok^=1;
		if( a[i]==ww&&ok==1 )	ok^=1,temp+=2;//^操作,0变1,1变0 
	}
	return temp;
}
int main()
{
	cin >> t;
	while( t-- )
	{	
		cin >> (a+1);
		int ans=0,n=strlen(a+1);
		memset(vis,0,sizeof(vis));
		for(int i=1;i<=n;i++)
		{
			vis[ a[i]-'0' ]++;
			ans=max(ans,vis[ a[i]-'0' ]);//奇数情况 
		}
		for(int i=0;i<=9;i++)
		for(int j=0;j<=9;j++)
		{
			if( i==j )	continue;
			ans=max(ans,run(i,j,n) );
		}
		cout << n-ans << endl;
	}
}

一起加油努力呀~

猜你喜欢

转载自blog.csdn.net/jziwjxjd/article/details/107680437