首页 > 代码库 > POJ1699 HDU 1560 Best Sequence(AC自动机 最短路)
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自动机 最短路)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。