题意:给你两个长度相等的字符串A和B,从A中选择一个可以为空的子串A[l1..r1],从B中选一个可以为空的子串B[l2..r2],满足r1=l2.然后把他们拼接在一起,求操作后的最长回文串的长度.
题解:我们可以先对A和B进行manacher(马拉车)预处理,然后我们枚举回文中心,每次选A和B中最长的回文串的中心,然后向两边进行拓展,如果A的回文串的左边的字符可以在B的右边找到的话,就能够形成回文,每次维护一个最大值.(枚举时A和B要错开一个位置,因为是拼接而成的,自己在纸上对着样例写一写就知道为什么了)。
代码:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <algorithm> 6 #include <stack> 7 #include <queue> 8 #include <vector> 9 #include <map> 10 #include <set> 11 #include <unordered_set> 12 #include <unordered_map> 13 #define ll long long 14 #define fi first 15 #define se second 16 #define pb push_back 17 #define me memset 18 const int N = 1e6 + 10; 19 const int mod = 1e9 + 7; 20 using namespace std; 21 typedef pair<int,int> PII; 22 typedef pair<long,long> PLL; 23 int n; 24 int len; 25 string s1,s2; 26 char str1[N],str2[N]; 27 int p1[N],p2[N]; 28 29 void init(){ 30 int cnt=2; 31 str1[0]='$'; 32 str1[1]='#'; 33 for(int i=0;i<n;++i){ 34 str1[cnt++]=s1[i]; 35 str1[cnt++]='#'; 36 } 37 str1[cnt]='\0'; 38 cnt=2; 39 str2[0]='$'; 40 str2[1]='#'; 41 for(int i=0;i<n;++i){ 42 str2[cnt++]=s2[i]; 43 str2[cnt++]='#'; 44 } 45 str2[cnt]='\0'; 46 } 47 48 void manacher(char *str,int *p){ 49 int id=0,mx=0; 50 for(int i=0;i<len;++i){ 51 if(i<mx) p[i]=min(mx-i,p[2*id-i]); 52 else p[i]=1; 53 for(;str[i-p[i]]==str[i+p[i]];p[i]++); 54 if(i+p[i]>mx){ 55 mx=i+p[i]; 56 id=i; 57 } 58 } 59 60 } 61 62 int main() { 63 ios::sync_with_stdio(false); 64 cin>>n>>s1>>s2; 65 len=n*2+2; 66 init(); 67 manacher(str1,p1); 68 manacher(str2,p2); 69 70 int ans=1; 71 for(int i=2;i<=len;++i){ 72 int tmp=max(p1[i],p2[i-2]); 73 while(str1[i-tmp]==str2[i+tmp-2]) tmp++; 74 ans=max(ans,tmp); 75 } 76 printf("%d\n",ans-1); 77 78 return 0; 79 }