ABB (2020牛客國慶集訓派對day1)

Jozky86發表於2020-10-01

ABB

題意:

長度為n的字串,問最少新增多少字元可以使其構成迴文字串

題解:

最長迴文字串我的第一反應是manacher馬拉車演算法,那我們直接馬拉車找到已有最長迴文串,然後總長度減去不就是答案嗎?非也 ~ ~ 。注意是讓我們構造最長迴文字串,我們會發現,如果我們用馬拉車找到的最長迴文串的最右端不是字串最右端,那此情況就相當於作廢
比如:
murderforajarofz
我們可以找到最長迴文串forajarof,但是最後一位z並不在裡面,那你無論怎麼構造也用不到forajarof這個迴文串,也就是我們要找最長的帶最後一個字元的迴文字串
我們直接在manacher的基礎上改就可以,原本式子中的ans,我們每查詢完一次清零,也就是如果找到的迴文串不是帶尾的不要,如果帶尾保留最大值
詳細看程式碼

程式碼:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 9*1e5+4;
char s[maxn];
char str[maxn];
int p[maxn];//表示以i為中心的最長迴文子串長度,

int init() {
    int len = strlen(s);
    str[0] = '@', str[1] = '#';
    int j = 2;
    for (int i = 0; i < len; ++i) str[j++] = s[i], str[j++] = '#';
    str[j] = '\0';
//    cout<<j<<endl;
    return j;
}
int manacher() {
   
	int len = init(),sum=-1; 
	int mx = 0;//同時記錄一個當前延伸最遠的迴文子串 
	int id = 0;//對稱中心 
	int ans = -1;
    for (int i = 1; i < len; ++i) {
    	
        if (i < mx) p[i] = min(p[id * 2 - i], mx - i);
        else p[i] = 1;
        while (str[i + p[i]] == str[i - p[i]]) p[i]++;
        //if(i+p[i]==len-1) 
        if (p[i] + i > mx) mx = p[i] + i, id = i;
     //   cout<<"id="<<id<<endl;
    	ans = max(ans, p[i] - 1);
		if(mx==len)sum=max(sum,ans);
		
		//cout<<"ans="<<ans<<endl;
    	//cout<<"mx="<<mx<<endl;
    	//cout<<"sum="<<sum<<endl;
 		ans=0;
	}
	return sum;
}
int main() 
{
	int t;
	cin>>t;
	for(int i=0;i<t;i++)cin>>s[i];
	if(manacher()==0)
	cout<<t-1<<endl;
	else 
  	cout <<t-manacher()<<endl;
    return 0;
}

相關文章