bzoj4044: [Cerc2014] Virus synthesis
阿新 • • 發佈:2019-03-07
div sca span clas dig isdigit -- ++ bzoj
做題要冷靜啊。。
仔細分析一下題面會發現這樣造串的方式,對於任意一個串一定是前面一堆+一個偶回文+後面一堆
答案就是把某一個回文造出來的代價+n-這個回文的長度
還有就是翻轉永遠不會劣於加字符
那麽把回文自動機造出來,把每個回文的最小步數搞出來就好了
假如是奇回文,直接f[pre]+2
偶的話分成兩種情況,由pre轉移過來和不由pre轉移
對於偶回文,最後一步一定是翻轉,那麽從pre轉移過來就是f[pre]+1,因為可以在pre翻轉之前先加一個字符
反之,就必須利用當前回文的最後一個字符,也就是把當前回文的一半搞出來
倍增跳fail找到第一個len*2<= now len 的點,用它翻轉再補滿一半再翻轉一次,就是f[u]+nowlen/2-len+1
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> using namespace std; const int _=1e2; const int maxn=1*1e5+_; const int maxc=4+3; const int mbit=17+3; int read() { int x=0,f=1; char ch=getchar();while(!isdigit(ch)){if(ch==‘-‘)f=-1;ch=getchar();} while(isdigit(ch)){x=x*10+ch-‘0‘;ch=getchar();} return x*f; } void write(int x) { if(x>=10)write(x/10); putchar(x%10+‘0‘); } int n,a[maxn];char ss[maxn]; void zxcv(int i) { if(ss[i]==‘A‘)a[i]=1; else if(ss[i]==‘C‘)a[i]=2; else if(ss[i]==‘G‘)a[i]=3; else a[i]=4; } struct Pnode { int w[maxc],len,dep,fail[mbit]; void clear() { len=0;dep=0; memset(w,0,sizeof(w)); memset(fail,0,sizeof(fail)); } };//fail樹中的深度,倍增找祖先 struct PAM { Pnode ch[maxn];int cnt,last; void init() { cnt=1;last=1; ch[0].clear(),ch[1].clear(); ch[0].len=0,ch[1].len=-1; ch[0].fail[0]=1; ch[0].dep=1; } int f[maxn]; void insert(int k,int x) { int pre=last; while(a[k]!=a[k-1-ch[pre].len]) pre=ch[pre].fail[0]; if(ch[pre].w[x]==0) { int now=++cnt; ch[now].clear(); ch[now].len=ch[pre].len+2; ch[now].dep=ch[pre].dep+1; int ppre=ch[pre].fail[0]; while(a[k]!=a[k-1-ch[ppre].len])ppre=ch[ppre].fail[0]; ch[now].fail[0]=ch[ppre].w[x]; for(int i=1;(1<<i)<=ch[now].dep;i++) ch[now].fail[i]=ch[ch[now].fail[i-1]].fail[i-1]; ch[pre].w[x]=now; //.........update............. if(ch[now].len==1)f[now]=1; else if(ch[now].len==2)f[now]=2; else if(ch[now].len%2==1)f[now]=f[pre]+2; else { f[now]=f[pre]+1; int u=now,b=0; while(1) { while(b>=0&&((1<<b)>ch[u].dep||ch[ch[u].fail[b]].len*2<=ch[now].len))b--; if(b<0)break; u=ch[u].fail[b]; b++; } u=ch[u].fail[0]; if(u!=0&&u!=1) f[now]=min(f[now],f[u]+ch[now].len/2-ch[u].len+1); } //..........getf.............. } last=ch[pre].w[x]; } }P; int main() { freopen("a.in","r",stdin); freopen("a.out","w",stdout); int T; T=read(); while(T--) { scanf("%s",ss+1);n=strlen(ss+1); P.init(); for(int i=1;i<=n;i++) { if(i==21) { int t;t++; } zxcv(i),P.insert(i,a[i]); } int ans=(1<<30); for(int i=2;i<=P.cnt;i++) { ans=min(ans,P.f[i]+n-P.ch[i].len); } write(ans);puts(""); } return 0; }
bzoj4044: [Cerc2014] Virus synthesis