HDU 2457 DNA repair AC自動機+dp
阿新 • • 發佈:2020-08-27
調了1天,居然是我的AC自動機板子有問題。。。
這個板子是真的繁瑣
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<map> #include<queue> #include<vector> #include<string> #include<fstream> using namespace std; #define rep(i, a, n) for(int i = a; i <= n; ++ i); #define per(i, a, n) for(int i = n; i >= a; -- i); typedef long long ll; const int N = 1e3 + 5; const int mod = 998244353; const double Pi = acos(- 1.0); const int INF = 0x3f3f3f3f; const int G = 3, Gi = 332748118; ll qpow(ll a, ll b) { ll res = 1; while(b){ if(b & 1) res = (res * a) % mod; a = (a * a) % mod; b >>= 1;} return res; } ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; } bool cmp(int a, int b){return a > b;} // map<char, int>mp; //AC自動機 struct Aho{ struct state{ int net[26]; int fail,cnt;// fail失配指標,到這個點有多少個點結束 }stateTable[N]; int ac_size; queue<int> que; void init(){ while(que.size()) que.pop(); for(int i = 0; i < N; ++ i){ memset(stateTable[i].net, 0, sizeof(stateTable[i].net)); stateTable[i].fail = stateTable[i].cnt=0; } ac_size = 0; } //建立trie樹 void ac_insert(char *S){ int n = strlen(S); int now = 0; for(int i=0;i<n;++i){ int si=mp[S[i]]; if(!stateTable[now].net[si]){ stateTable[now].net[si] = ++ ac_size; } now = stateTable[now].net[si]; } stateTable[now].cnt = 1; } //建立fail指標 void ac_build(){ for(int i = 0; i < 4; ++ i){ if(stateTable[0].net[i]) que.push(stateTable[0].net[i]); } while(que.size()){ int p = que.front(); que.pop(); for(int j = 0; j < 4; ++ j){ int c = stateTable[p].net[j]; if(!c) stateTable[p].net[j] = stateTable[stateTable[p].fail].net[j]; else{ que.push(c); stateTable[c].fail = stateTable[stateTable[p].fail].net[j]; stateTable[c].cnt |= stateTable[stateTable[c].fail].cnt; } } } } // int ac_get(int u){ int res=0; while(u){ res+=stateTable[u].cnt; stateTable[u].cnt=0; u=stateTable[u].fail; } return res; } //計算 int ac_match(char *S){ int n =strlen(S); int res = 0, now = 0; for(int i=0;i<n;++i){ int si=S[i]-'a'; if(stateTable[now].net[si]) now=stateTable[now].net[si]; else{ int p=stateTable[now].fail; while(p!=-1&&!stateTable[p].net[si])p = stateTable[p].fail; if(p==-1) now=0; else now=stateTable[p].net[si]; } if(stateTable[now].cnt) res+=ac_get(now); } return res; } }aho; int T,n; char s[N]; int dp[N][N], res, Case = 0; int solve(){ int len = strlen(s + 1); memset(dp, 0x3f, sizeof(dp)); dp[0][0] = 0; for(int i = 1; i <= len; ++ i){ for(int j = 0; j <= aho.ac_size; ++ j){ for(int k = 0; k < 4; ++ k){ int tp = aho.stateTable[j].net[k]; if(aho.stateTable[tp].cnt) continue; dp[i][tp] = min(dp[i][tp], dp[i - 1][j] + (mp[s[i]] != k)); } } } res = INF; for(int j = 0; j <= aho.ac_size; ++ j){ res = min(res, dp[len][j]); } if(res == INF) return -1; return res; } int main() { mp['A'] = 0, mp['T'] = 1, mp['G'] = 2, mp['C'] = 3; while(~scanf("%d",&n) && n){ aho.init(); for(int i = 1; i <= n; ++ i){ scanf("%s",s); aho.ac_insert(s); } aho.ac_build(); scanf("%s",s + 1); printf("Case %d: %d\n",++ Case, solve()); } return 0; }