标签:scan space algorithm rev 操作 字符 printf reverse return
题目描述:
#include<queue> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define N 100050 int T,n; char s[N]; struct pnt { int pre,len,trs[4]; void clear() { pre=len=trs[0]=trs[1]=trs[2]=trs[3]=0; } }p[N]; int ci(char c) { if(c==‘A‘)return 0; if(c==‘G‘)return 1; if(c==‘C‘)return 2; return 3; } int dp[N],ans; struct PAM { int tot,las; void res() { p[0].clear(),p[1].clear(); tot=las=1; p[0].pre=p[1].pre=1; p[1].len=-1; memset(dp,0x3f,sizeof(dp)); } bool mis(int i,int x) { return s[i]!=s[i-p[x].len-1]; } void insert(int i) { int lp = las; while(mis(i,lp))lp=p[lp].pre; int c = ci(s[i]); if(!p[lp].trs[c]) { int np = ++tot; p[np].clear(); int tmp = p[lp].pre; while(mis(i,tmp))tmp=p[tmp].pre; p[np].pre=p[tmp].trs[c]; p[np].len=p[lp].len+2; p[lp].trs[c]=np; } las=p[lp].trs[c]; } int fa[N][21]; void init() { for(int i=0;i<=tot;i++)fa[i][0]=p[i].pre; for(int i=1;i<=20;i++) for(int j=0;j<=tot;j++) fa[j][i]=fa[fa[j][i-1]][i-1]; } int get_mid(int u) { int ret = u; for(int i=20;i>=0;i--) if(p[fa[ret][i]].len*2>=p[u].len)ret=fa[ret][i]; while(p[ret].len&1||p[ret].len*2>p[u].len)ret=p[ret].pre; return ret; } void DP() { dp[0]=0; queue<int>q; for(int i=0;i<4;i++) if(p[0].trs[i]) { dp[p[0].trs[i]]=2; q.push(p[0].trs[i]); } ans = n; while(!q.empty()) { int u = q.front(); q.pop(); int mid = get_mid(u); dp[u]=min(dp[u],dp[mid]+p[u].len/2-p[mid].len+1); ans=min(ans,dp[u]+n-p[u].len); for(int i=0;i<4;i++) if(p[u].trs[i]) { dp[p[u].trs[i]]=dp[u]+1; q.push(p[u].trs[i]); } } } }pam; int main() { scanf("%d",&T); while(T--) { scanf("%s",s+1); n = strlen(s+1); pam.res(); for(int i=1;i<=n;i++) pam.insert(i); pam.init(); pam.DP(); printf("%d\n",ans); } return 0; }
标签:scan space algorithm rev 操作 字符 printf reverse return
原文地址:https://www.cnblogs.com/LiGuanlin1124/p/10127214.html