这题题意是给你一个只由ATCG组成字符串,让你用ATCG去构造它,两种操作,1.把当前构造的字符向左或右复制,2向当前构造的字符串向左或右添加一个字符
思路:在回文自动机上dp
![]()
这题清空得优化一下,不然会tle
#include<cstdio>
#include<cstring>
#define ll long long
#include<algorithm>
#define maxn 205000
#include<math.h>
#include<map>
#include<unordered_map>
#define ll long long
using namespace std;
int tre[maxn][5],len[maxn],cnt,fail[maxn],last,half[maxn],dp[maxn];
char s[maxn];
void init()
{
//memset(fail,0,sizeof(fail));
//memset(tre,0,sizeof(tre));
//memset(len,0,sizeof(len));
//memset(dp,0,sizeof(dp));
for(int i=0;i<=cnt+5;i++)
{
memset(tre[i],0,sizeof(tre[i]));
len[i]=0;
}
s[0]='#';
len[0]=0;
len[1]=-1;
cnt=1;
fail[0]=1;
last=0;
half[0]=half[1]=0;
}
int get_fail(int x,int n)
{
while(s[n-len[x]-1]!=s[n])
x=fail[x];
return x;
}
int main()
{
int k=0;
int t;
scanf("%d",&t);
while(t--)
{
init();
scanf("%s",s+1);int ans=1e9,tot=strlen(s+1);
for(int i=1; s[i]!='\0'; i++)
{
int x;
if(s[i]=='A')
s[i]='a';
else if(s[i]=='T')
s[i]='b';
else if(s[i]=='C')
s[i]='c';
else
s[i]='d';
x=s[i]-'a';
int y;
last=get_fail(last,i);
if(!tre[last][x])
{
len[++cnt]=len[last]+2;
int q=fail[last];
q=get_fail(q,i);
fail[cnt]=tre[q][x];
tre[last][x]=cnt;
//ans[cnt]=ans[fail[cnt]]+1;
if (len[cnt]==1)
half[cnt]=0;
else
{
int pos=half[last];
while ( s[i - len[pos] - 1] != s[i]||len[pos]+2>len[cnt]/2 )
pos = fail[pos] ;
half[cnt]=tre[pos][x];
}
if (len[cnt]&1)
dp[cnt]=dp[fail[cnt]]+len[cnt]-len[fail[cnt]];
else if (len[cnt]<=2)
dp[cnt]=len[cnt];
else
dp[cnt]=min(dp[last]+1,dp[half[cnt]]+len[cnt]/2-len[half[cnt]]+1);
}
last=tre[last][x];
ans=min(ans,dp[last]+tot-len[last]);
}
printf("%d\n",ans);
}
}