2018 Benelux Algorithm Programming Contest (BAPC 18) G-Game Night(滚动)

题意

给一个只含ABC的字符串,

要求把字符串的A放在一起B放在一起C放在一起,

问最少有多少个字母需要被移动位置。

思路来源

翼神

题解

就是一波暴力啊,和秦皇岛那个字符串暴力题很像。

全排列ABC、ACB、BCA、BAC、CAB、CBA六种,

考虑是圆串,所以可简化为ABC、ACB两种,

预处理两个串,然后与原串暴力匹配即可,

原串也是圆串,所以将其重复一遍展成线性串。

统计一次的不同个数是O(n),然后用到滚动技巧。

这其实和滚动哈希那里线性求值差不多QAQ,也不知道是不是尺取。

A、B、C三部分向前滚动,l++,r++,修改下标更改时的值。

具体看代码吧,写的很丑.jpg

代码

#include 
#include  
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
const int INF=0x3f3f3f3f;
const int maxn=1e5+10; 
const int mod=1e9+7;
const int MOD=998244353;
const double eps=1e-7;
typedef long long ll;
#define vi vector 
#define si set
#define pii pair 
#define pi acos(-1.0)
#define pb push_back
#define mp make_pair
#define lowbit(x) (x&(-x))
#define sci(x) scanf("%d",&(x))
#define scll(x) scanf("%lld",&(x))
#define sclf(x) scanf("%lf",&(x))
#define pri(x) printf("%d",(x))
#define rep(i,j,k) for(int i=j;i<=k;++i)
#define per(i,j,k) for(int i=j;i>=k;--i)
#define mem(a,b) memset(a,b,sizeof(a)) 
using namespace std;
int n,a,b,c,len;
string s,t,u,v,Q[3];
int check(string a,string b)
{
	int num=0,len=a.size();
	rep(i,0,len-1)if(a[i]!=b[i])num++;
	return num;
}
int solve()
{
	int ans=INF;
	rep(i,0,a-1)Q[0]+='A';
	rep(i,0,b-1)Q[1]+='B';
	rep(i,0,c-1)Q[2]+='C';
	string s1="",s2="";
	s1+=Q[0],s1+=Q[1],s1+=Q[2];
	s2+=Q[0],s2+=Q[2],s2+=Q[1];
	int ini1=check(s1,t),tmp1=ini1;
	rep(i,1,len-1)
	{
	  if(s[i-1]=='A')tmp1++;
	  if(s[i-1+a]=='A')tmp1--;
	  if(s[i-1+a]=='B')tmp1++;
	  if(s[i-1+a+b]=='B')tmp1--;
	  if(s[i-1+a+b]=='C')tmp1++;
	  if(s[i-1+a+b+c]=='C')tmp1--;
	  ini1=min(ini1,tmp1);
	  //printf("%d:%d\n",i,tmp1);
	}
	int ini2=check(s2,t),tmp2=ini2;
	rep(i,1,len-1)
	{
	  if(s[i-1]=='A')tmp2++;
	  if(s[i-1+a]=='A')tmp2--;
	  if(s[i-1+a]=='C')tmp2++;
	  if(s[i-1+a+c]=='C')tmp2--;
	  if(s[i-1+a+c]=='B')tmp2++;
	  if(s[i-1+a+b+c]=='B')tmp2--;
	  ini2=min(ini2,tmp2);
	}
	ans=min(ans,ini1);
	ans=min(ans,ini2);
	return ans;
}
//ABC ACB 
int main()
{ 
   sci(n);
   cin>>s;
   len=s.size();
   rep(i,0,len-1)
   {
   	if(s[i]=='A')a++;
   	else if(s[i]=='B')b++;
   	else c++;
   }
   t=s;s+=t;
   printf("%d\n",solve());
   return 0;
}

 

你可能感兴趣的:(思维题,滚动)