POJ1699 HDU 1560 Best Sequence(AC自动机 最短路)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ1699 HDU 1560 Best Sequence(AC自动机 最短路)相关的知识,希望对你有一定的参考价值。
曾写过迭代加深搜索的方法,现在使用在AC自动上跑最短路的方法
dp[i][j]表示状态为到节点i,模式串是否包含的状态为j的最短串的长度,则状态转移方程为:
dp[nx][ny] = min(dp[x][y] + 1) , 其中nx为x后继结点,ny为从y转移过来的新状态,更新时加入队列
#include<cstdio> #include<iostream> #include<cstdlib> #include<cstring> #include<algorithm> #include<queue> #include<set> #include<string> using namespace std; int Hash[128]; typedef long long LL; const int N = 150, CH = 4, INF = 0x3F3F3F3F; int n, cnt; struct Trie{ Trie *next[CH]; Trie *fail; int id; }tree[N], *q[50000]; int chi[N][CH]; int sum[N]; int dp[N][1024]; bool inq[N][1024]; class ACauto{ private: int nxt; Trie *root; public: ACauto(){ root = &tree[0]; nxt=0; memset(&tree[0], 0, sizeof(Trie)); } void insert(string s, int id){ Trie *p = root; for(int i = 0; i < s.size(); i++){ int c = Hash[s[i]]; if(!p -> next[c]){ memset(&tree[++nxt], 0, sizeof(Trie)); p -> next[c] = &tree[nxt]; p -> next[c] -> id = nxt; } p = p -> next[c]; } sum[p->id] = 1 <<id; } void build(){ int front = 0, rear = 0; q[rear++] = root; root -> fail = NULL; while(front < rear){ Trie *cur = q[front++]; if(cur -> fail){ sum[cur->id] |= sum[cur->fail ->id]; } for(int i = 0; i < CH; i++){ Trie *son = cur -> next[i]; Trie *tp = (cur == root)? root: cur -> fail->next[i]; if(son == NULL){ cur -> next[i] = tp; }else{ son -> fail = tp; q[rear++] = son; } son = cur -> next[i]; chi[cur->id][i] = son->id; } } } void solve(){ memset(dp, 0x3F, sizeof(dp)); memset(inq, 0, sizeof(inq)); queue<int> q; dp[0][0] = 0; inq[0][0] = 1; int st = 1 << cnt; q.push(0); while(!q.empty()){ int u = q.front(); q.pop(); int x = u / st; int y = u % st; inq[x][y] = 0; for(int i = 0 ; i < CH; i++){ int nx = chi[x][i], ny = y | sum[chi[x][i]]; if(dp[nx][ny] > dp[x][y] + 1){ dp[nx][ny] = dp[x][y] + 1; if(!inq[nx][ny]){ q.push(nx * st + ny); inq[nx][ny] = 1; } } } } int ans = INF; for(int i = 0; i <= nxt; i++){ ans = min(ans, dp[i][st - 1]); } printf("%d\n", ans); } }; char str[100]; int main(){ Hash[‘A‘] = 0; Hash[‘C‘] = 1; Hash[‘G‘] = 2; Hash[‘T‘] = 3; int t; cin>>t; while(t--){ int n; cin>>n; set<string> st; for(int i = 0; i < n; i++){ string str; cin>>str; st.insert(str); } ACauto ac; memset(sum, 0, sizeof(sum)); cnt = 0; for(set<string>::iterator it = st.begin(); it != st.end(); it++){ ac.insert(*it, cnt++); } ac.build(); ac.solve(); } return 0; }
以上是关于POJ1699 HDU 1560 Best Sequence(AC自动机 最短路)的主要内容,如果未能解决你的问题,请参考以下文章