日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

P4762-[CERC2014]Virus synthesis【PAM,dp】

發布時間:2023/12/3 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 P4762-[CERC2014]Virus synthesis【PAM,dp】 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

正題

題目鏈接:https://www.luogu.com.cn/problem/P4762


題目大意

長度為nnn的目標串,開始一個空串,可以執行以下操作

  • 在頭或者尾加一個字符
  • 復制一個該串的逆串放在后面
  • 求最少操作次數。


    解題思路

    我們可以知道答案肯定是一個回文串然后剩下的暴力加上。

    我們構建一個PAMPAMPAM,然后用fif_{i}fi?表示帶該回文串需要的最少次數。

    對于一個節點的轉移有fy=min{fx+1}f_{y}=min\{f_{x}+1\}fy?=min{fx?+1}
    就是該回文串頭尾各加上一個字符。

    該回文串還有可能是一個雙倍回文,即一個回文串在復制一個逆串后回文,那么有我們要像[SHOI2011]雙倍回文這道題目一樣維護一個最長的不超過該串一半的回文后綴的節點halfihalf_ihalfi?。

    然后有轉移
    fx=min{fhalfx+1+lenx2?lenhalfx}f_{x}=min\{f_{half_x}+1+\frac{len_x}{2}-len_{half_x}\}fx?=min{fhalfx??+1+2lenx???lenhalfx??}

    然后答案就是min{n?lenx+fx}min\{n-len_x+f_{x}\}min{n?lenx?+fx?}

    時間復雜度O(4Tn)O(4Tn)O(4Tn)

    如果用stdstdstd自帶隊列會比較慢需要自行卡常。


    codecodecode

    #include<cstdio> #include<cstring> #include<algorithm> #include<queue> using namespace std; queue<int> q; const int N=1e5+10; int T,n,m,half[N],f[N],ans; int len[N],fail[N],next[N][4],cnt; char s[N]; int z(char x){if(x=='A') return 0;if(x=='C') return 1;if(x=='G') return 2;if(x=='T') return 3; } int get_fail(int x,int n){while(s[n-len[x]-1]!=s[n])x=fail[x];return x; } void Make_PAM(){int last=0;len[1]=-1;s[0]='#';cnt=fail[0]=1;for(int i=1;i<=n;i++){int val=z(s[i]),x=get_fail(last,i);if(!next[x][val]){len[++cnt]=len[x]+2;int y=get_fail(fail[x],i);fail[cnt]=next[y][val];if(len[cnt]<=2) half[cnt]=fail[cnt];else{int z=half[x];while(s[i-len[z]-1]!=s[i]||((len[z]+2)<<1)>len[cnt])z=fail[z];half[cnt]=next[z][val];}next[x][val]=cnt;}last=next[x][val];}return; } void Solve(){ans=n;for(int i=2;i<=cnt;i++)f[i]=len[i];f[0]=1;q.push(0);while(!q.empty()){int x=q.front();q.pop();f[x]=min(f[x],f[half[x]]+1+len[x]/2-len[half[x]]);ans=min(ans,n-len[x]+f[x]);for(int i=0;i<4;i++){int y=next[x][i];if(!y) continue;f[y]=min(f[y],f[x]+1);q.push(y);}}return; } int main() {scanf("%d",&T);while(T--){for(int i=0;i<=cnt;i++)for(int j=0;j<4;j++)next[i][j]=0;scanf("%s",s+1);n=strlen(s+1);Make_PAM();Solve();printf("%d\n",ans);}return 0; }

    總結

    以上是生活随笔為你收集整理的P4762-[CERC2014]Virus synthesis【PAM,dp】的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。