Set F[x] to get the minimum number of steps for the palindrome of X, then Ans=min (N-len[x]+f[x])
A f[string]=1 with a length of 0 in the boundary condition
Because the flip will only get even palindrome string, so f[]= the length of the string
For an even palindrome string x, set Y to X to remove the end-to-end string, with f[x]=f[y]+1
Set Y as the longest palindrome suffix of x with a length not exceeding X, with f[x]=len[x]/2-len[y]+f[y]+1
Take a minimum value in both cases.
For the representation of the state and the longest palindrome suffix of the query, with a palindrome tree support operation can be. Time complexity $o (n) $.
#include <cstdio> #include <cstring>const int n=100010,s=4;int T,n,i,x,y,ans,all,son[n][s],fail[n],trans [N],f[n],len[n],text[n],last,tot,q[n],h,t;char s[n];inline int newnode (int l) {for (int i=0;i<s;i++) son[tot][i]=0; Len[tot]=l; return tot++;} inline void init () {last=tot=all=0; NewNode (0), NewNode (-1); Text[0]=-1,fail[0]=1;} inline int getfail (int x) {while (Text[all-len[x]-1]!=text[all]) x=fail[x]; return x;} inline void Add (int w) {text[++all]=w; int X=getfail (last); if (!son[x][w]) {int y=newnode (len[x]+2); Fail[y]=son[getfail (Fail[x])][w]; if (len[y]<=2) trans[y]=fail[y];else{int z=trans[x]; while (text[all-len[z]-1]!=text[all]| | (len[z]+2) *2>len[y]) z=fail[z]; TRANS[Y]=SON[Z][W]; } son[x][w]=y; } Last=son[x][w];} inline int hash (char c) {if (c== ' A ') return 0; if (c== ' T ') return 1; if (c== ' C ') return 2; return 3;} inline void up (Int&a,int b) {if (a>b) a=b;} int main () {for (scanf ("%d", &t); t--;p rintf ("%d\n", ans)) {scanf ("%s",s+1), Ans=n=std::strlen (s+1); For (Init (), i=1;i<=n;i++) Add (hash (s[i])); for (i=2;i<tot;i++) if (len[i]&1) f[i]=len[i]; F[q[h=t=0]=0]=1; while (h<=t) for (x=q[h++],i=0;i<4;i++) if (Son[x][i]) {f[y=son[x][i]]=f[x]+1; Up (f[y],len[y]/2-len[trans[y]]+f[trans[y]]+1); Up (Ans,n-len[y]+f[y]); Q[++t]=y; }} return 0;}
BZOJ4044: [Cerc2014] Virus synthesis