あなたは、4つの文字が2回の操作で指定した文字列を綴るATGCを使用します。
1は、その内の文字列は、先頭または末尾に置かれています。
2.既存の文字列の先頭または尾に続いて、既存の文字列をコピーし、リバース。
最初は空の文字列を持っています。操作の必要な最小数。
のみ<= 100000
問題解決の時間
特定のパリンドローム配列後の非空の文字列が2操作後一度もあります。
だから、PAMを構築DP検討しました。
偶数のみパリンドローム配列は、2の操作によって生成することができるので、これだけパリンドローム配列もDP参加します。
PAMの$ xには$上の点の場合:
文字列は、2つの文字の後に除去される場合、$ Yが非空の文字列を$、その後明らかに$ X $ Y $ 2と前の文字を取得するための操作で行うことができる$、$ DP [X] = DP [Y] +1 $。
$ Y $が空の場合、少なくとも二つの動作は、$ DP [X] = 2 $。
$ X $は$ LEN / 2 $サフィックス拡張文字列回文コピーを超えない長さで作ることができる最初のジャンプがより$ lenの/ 2 $列は= [X] Y $、$ DPを$以上での長さを見つけることができない乗算、来DP [Y] +(LEN [X] / 2-lenを[Y])+ 1 $。
#include<bits/stdc++.h>
using namespace std;
namespace RKK
{
const int N=100011;
char str[N];int n;
int cc(char ch)
{
switch(ch)
{
case 'A':return 0;
case 'G':return 1;
case 'C':return 2;
case 'T':return 3;
default:return 114514;
}
}
queue<int> q;
struct remilia{int tranc[4],len,fail;void set(){memset(this,0,24);}};
struct sakuya
{
remilia p[N];
int size,fin;
int fa[N][20];
int dp[N];
void set()
{
p[0].set(),p[1].set();
p[0].len=0,p[1].len=-1;
p[0].fail=p[1].fail=1;
memset(dp,0,(size+1)*sizeof(int));
size=fin=1;
}
sakuya(){size=fin=1;this->set();}
int match(char *s,int i,int px){return s[i-p[px].len-1]==s[i];}
void ins(char *s,int i)
{
int ch=cc(s[i]);
int npx,lpx,lpy;
lpx=fin;
while(!match(s,i,lpx)) lpx=p[lpx].fail;
if(!p[lpx].tranc[ch])
{
npx=++size;p[npx].set();
p[npx].len=p[lpx].len+2;
lpy=p[lpx].fail;
while(!match(s,i,lpy)) lpy=p[lpy].fail;
p[npx].fail=p[lpy].tranc[ch];
p[lpx].tranc[ch]=npx;
}
fin=p[lpx].tranc[ch];
}
int find(int x)
{
int l=p[x].len/2;
for(int k=19;k>=0;k--)if(p[fa[x][k]].len>l) x=fa[x][k];
while(p[x].len&1||p[x].len>l) x=fa[x][0];
return x;
}
void work()
{
for(int i=0;i<=size;i++) fa[i][0]=p[i].fail;
for(int k=1;k<20;k++)for(int i=0;i<=size;i++) fa[i][k]=fa[fa[i][k-1]][k-1];
dp[0]=0;for(int i=0;i<4;i++)if(p[0].tranc[i]) dp[p[0].tranc[i]]=2,q.push(p[0].tranc[i]);
int ans=n;
while(!q.empty())
{
int x=q.front();q.pop();
int f=find(x);
dp[x]=min(dp[x],dp[f]+p[x].len/2-p[f].len+1);
ans=min(ans,n-p[x].len+dp[x]);
for(int i=0;i<4;i++)if(p[x].tranc[i]) dp[p[x].tranc[i]]=dp[x]+1,q.push(p[x].tranc[i]);
}
printf("%d\n",ans);
}
}pam;
int TAT;
int Iris()
{
scanf("%d",&TAT);
while(TAT--)
{
scanf("%s",str+1),n=strlen(str+1);
for(int i=1;i<=n;i++) pam.ins(str,i);
pam.work();
pam.set();
}
return 0;
}
}
int main(){return RKK::Iris();}