Description
The JYY has two strings A and b with a length of N.
A "twist string s (i,j,k) substring consisting of the I character in A to the first J character
Concatenation with a substring of the J character in B to the K-character.
For example, if a= ' XYZ ', b= ' UVW ', then twist the string s (#) = ' XYVW '.
Jyy defines a "twisted palindrome" for one of the following situations:
A palindrome string in the 1.A;
A palindrome string in the 2.B;
3. Or a palindrome twist string s (i,j,k)
Now Jyy want to find the longest twist palindrome.
Input
The first line consists of a positive integer n.
The second line contains an uppercase string A with a length of N.
The third line contains a string B with a length of N, consisting of uppercase letters.
1≤n≤10^5
Output
The first line of the output is an integer that represents the longest twisting palindrome string.
Sample Input
5
ABCDE
Baecb
Sample Output
5
HINT
The twist palindrome in the best scenario is shown below (the characters in the palindrome are not used.):
. Bc..
.. ECB
First, we need to know two things about the twisted palindrome.
1, it is a string or string B substring
2, its symmetry center has a part in a string or B string
For the first situation is very good to write, there is no more to say, mainly to talk about the second situation
For the second case, we first enumerate the palindrome string midpoint I, and then find the maximum expansion of the maximum range (I-p[i]~i+p[i]), if the palindrome string in the midpoint of a string, then a string can continue to fetch the range is (1~i-p[i]-1), and B string can be taken in the range is (i+p[i]~ Len), if the center point is similar in string B.
So what do we do next? Two-minute length. A length of two, and then judge whether part of a is the same as a part of B string
How to judge? Hash. Record the hash out of the value of the prefix and the B string record suffix and, judging by the time do similar prefixes and subtraction can, remember double hash
Still don't understand? On the Code
#include <cmath> #include <cstdio> #include <cstring> #include <iostream> #include < Algorithm> #define INF 0x7f7f7f7fusing namespace std;typedef long long ll;typedef unsigned int ui;typedef unsigned long Long Ull;inline int read () {int X=0,f=1;char ch=getchar (); for (;ch< ' 0 ' | | Ch> ' 9 '; Ch=getchar ()) if (ch== '-') f=-1; for (; ch>= ' 0 ' &&ch<= ' 9 '; Ch=getchar ()) x= (x<<1) + (x<<3) +ch-' 0 '; return x*f;} inline void print (int x) {if (x>=10) print (X/10); Putchar (x%10+ ' 0 ');} const int N=1e5,limit=27,p1=100007,p2=233333;char a[n*2+10],b[n*2+10];int Pa[n*2+10],pb[n*2+10];int sumA[2][N*2+10] , Sumb[2][n*2+10],g[2][n*2+10];int len,ans;void work (char *s,int *p) {int max=0,id=0; for (int i=1;i<=len;i++) {p[i]=max>i?min (p[id*2-i],max-i): 1; while (S[i+p[i]]==s[i-p[i]]) p[i]++; if (max<p[i]+i) max=p[id=i]+i; }}bool Check (int l1,int r1,int l2,int r2,int Len) {//hash judgment, using prefix and int x= (SUMA[0][R1]-1LL*SUMA[0][L1-1]*G[0][LEN]%P1)%p1; int y= (SUMB[0][L2]-1LL*SUMB[0][R2+1]*G[0][LEN]%P1)%p1; x= (X+P1)%p1,y= (Y+P1)%p1; if (x!=y) return 0; x= (SUMA[1][R1]-1LL*SUMA[1][L1-1]*G[1][LEN]%P2)%p2; Y= (SUMB[1][L2]-1LL*SUMB[1][R2+1]*G[1][LEN]%P2)%p2; x= (X+P2)%p2,y= (Y+P2)%p2; return x==y;} int solve (int j,int k) {//two min enumeration length int l=0,r=min (j, (Len>>1)-k+1), ans=0; while (l<=r) {int mid= (L+R) >>1; if (check (j-mid+1,j,k,k+mid-1,mid)) L=mid+1,ans=mid; else r=mid-1; } return ans; int main () {len=read (); scanf ("%s%s", a+1,b+1); for (int i=len;i;i--) a[i<<1]=a[i],b[i<<1]=b[i],a[i<<1|1]=b[i<<1|1]= ' & '; len=len<<1|1; a[0]=b[0]= ' # ', a[1]=b[1]= ' & ', a[len+1]=b[len+1]= ' ^ ', g[0][0]=g[1][0]=1; Work (A,PA), work (B,PB); for (int i=1;i<=len;i++) pa[i]--, pb[i]--; Palindrome string length will be more than one, should be subtracted for (int i=1;i<=len;i++) Ans=max (Ans,max (Pa[i],pb[i])),//palindrome string for the case of a substring g[0][i]=1ll* g[0][i-1]*LIMIT%P1, G[1][I]=1LL*G[1][I-1]*LIMIT%P2; Record something like the binary for (int i=2;i<len;i+=2) suma[0][i>>1]= (1ll*suma[0][(i>>1) -1]*limit+a[i])%P1, Suma[1][i>>1]= (1ll*suma[1][(i>>1) -1]*limit+a[i])%p2; Record two hash prefixes and one extra bit at a time to multiply the last binary (limit) for (int i=len-1;i>1;i-=2) sumb[0][i>>1]= (1ll*sumb[0][(i>>1) +1] *limit+b[i])%p1, sumb[1][i>>1]= (1ll*sumb[1][(i>>1) +1]*limit+b[i])%p2; Because of symmetry, so the record of B string to start from the back for (int i=2;i<len;i++) {//Palindrome center in the case of a string int l=i-pa[i],r=i+pa[i]; L= (l+1) >>1,r>>=1; Ans=max (Ans,pa[i]+solve (l-1,r)); } for (int i=2;i<len;i++) {//palindrome string Center in B string case int l=i-pb[i],r=i+pb[i]; L= (l+1) >>1,r>>=1; Ans=max (Ans,pb[i]+solve (l,r+1)); } printf ("%d\n", Ans); return 0;}
[Jsoi2016] Twist the palindrome string