superoj779 檸檬的密碼

題目描述

輸入格式

輸入數據第一行包含一個正整數 N ,表示字符串的長度。 
數據第二行包含一個長度爲 N 的字符串,僅由小寫字母組成,表示需要破譯的字符串。

輸出格式

輸出數據僅包含一個整數,表示最長可能的密碼的長度。

樣例數據 1

輸入  [複製]

25 
orzabcdxyzefgfeqwertydcba

輸出

13

備註

【樣例說明】 
最長的可能的密碼是“abcdefgfedcba”,長度爲 13 。
Lemon 選擇的 x=4
Left="abcd"
Right="dcba"
Mid="efgfe"
A="orz"
B="xyz"
C="qwerty"

【數據範圍】 
對於 20% 的數據,滿足N<=20 
對於 40% 的數據,滿足N<=300 
對於 60% 的數據,滿足N<=2000 
對於 100% 的數據,滿足N<=100000


解析:

     首先對於中間的迴文串,取最長一定是最優的

所以先用manacher預處理以每個點爲中心的最長迴文O(n)

最後一段的翻轉==開頭段

又因爲C可能爲空,所以用kmp預處理每個點爲最後一段開頭的最長匹配v【i】

因爲我們只用最優解,不需要一定以 i 結尾,所以f【i】=max(f【i-1】,v【i】)

到此,全部預處理出來了,剩下只需要枚舉中心算ans了

時間複雜度O(N)

代碼

//manacher + KMP
#include<string>
#include<cstring>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
using namespace std;
int n;
char c[100010];
int p[100010];     //manacher
char r[100010];     //l m r
int next[100010];
int f[100010];    //kmp

int main()
{
	//freopen("password.in","r",stdin);
	//freopen("password.out","w",stdout);
	int i,j,k,s,t;
	scanf("%d\n",&n);
	scanf("%s",c+1);    //從1開始存 
	int id=0;   
	int mx=0;     //最邊境+1 
	for(i=1;i<=n;i++)
	  {
	  	if(mx>i) 
	  	  p[i]=min(p[id*2-i],mx-i);   //對稱點與邊境 
	  	else
		  p[i]=1;
		while(c[i-p[i]]==c[i+p[i]]&&i-p[i]>0) p[i]++;  
		if(i+p[i]>mx)
		 {
		 	mx=i+p[i];
		 	id=i;
		 }      
	  }
	  int ans=0;
	  k=0;
  	  	for(j=n;j>=1;j--)
	  	  {
            k++;
			r[k]=c[j];  
		  } 	
		next[0]=-1;        //控制搜到root的next 
		for(j=1;j<=k;j++)
		   {next[j]=0;}  
	  	for(j=2;j<=k;j++)
	  	  {
	  	  	 for(s=next[j-1];s>=0;s=next[s])
	  	  	   {
	  	  	   	 if(r[j]==r[s+1]) {next[j]=s+1; break;}
			   }
		  }
	  	int v=0;
	  	int maxx=0;
	  	for(j=1;j<=n;j++)
		  {
		  	 while(c[j]!=r[v+1]&&(v>0))
               v=next[v];
             if(c[j]==r[v+1]) v++;
			 f[j]=max(v,f[j-1]);  
			 if(v==n) break;
		  }
	
	  
	  
	int dd;
	 v=0; 
	for(i=2;i<n;i++)   //枚舉mid 
	  {
	  	dd=n-(i+p[i])+1;
    
             v=min(dd,f[i-p[i]]); 	
        
		if((p[i]*2-1+v*2)>ans) ans=p[i]*2-1+v*2;  
	  }
	
	cout<<ans;
	
	return 0;
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章