1. 程式人生 > >2018 Benelux Algorithm Programming Contest (BAPC 18) G-Game Night(滾動)

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 <iostream>
#include <algorithm> 
#include <cstring>
#include <cstdio>
#include <cmath>
#include <set>
#include <map>
#include <vector>
#include <stack>
#include <queue>
#include <functional>
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<int> 
#define si set<int>
#define pii pair<int,int> 
#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;
}