好久没刷 poj 了,今天练习 AC 自动机时去水了一发喵~
在 poj 上 A 题的感觉并没有 BZOJ 上那么愉悦,准确的说是痛不欲生
真是应了那句老话,你再慢也有比你慢的,你再快也有比你快的……
跪求那些 0ms 的代码啊,还有那么多人都只跑了 32ms 啊!!
果然还是我太弱了吗?一定是我还太弱了 TAT
一道裸裸的 AC 自动机上 dp
令 dp[i][j] 表示母串的前 i 个字母遍历 AC 自动机,使之到达 j 节点,至少要修改多少个字母
dp[i+1][k]=min(dp[i+1][k], dp[i][j]+CHAR(j->k)!=s[i]) { k 不为匹配点}
CHAR(j->k) 是指在 AC 自动机上从点 j 转移到点 k 的边时经过的字母
答案就是 min{dp[len(s)][i]} 了喵~
我才不会说我是来晒我的 AC 自动机代码的呢~ (虽然被 poj 的各大神犇搞得一点优越感都没有……)
1 #include <cstdio> 2 #include <cstring> 3 const int inf=0x3F3F3F3F; 4 const int sizeOfText=1024; 5 const int sizeOfType=4; 6 const int sizeOfMemory=1024; 7 8 namespace trieDfa 9 { 10 struct node 11 { 12 int idx; 13 bool end; 14 node * fail; 15 node * ch[sizeOfType]; 16 }; 17 node * dfa; 18 node memory[sizeOfMemory]; int port; 19 node * E[sizeOfMemory]; 20 inline node * newnode() 21 { 22 node * ret=memory+port; 23 E[ret->idx=port++]=ret; 24 ret->end=0; 25 ret->fail=NULL; 26 memset(ret->ch, 0, sizeof(ret->ch)); 27 return ret; 28 } 29 inline void clear() {port=0; dfa=newnode();} 30 31 inline int ord(char ch) 32 { 33 switch (ch) 34 { 35 case 'A':return 0; 36 case 'G':return 1; 37 case 'C':return 2; 38 case 'T':return 3; 39 } 40 } 41 inline void insert(char * s) 42 { 43 int len=strlen(s); 44 node * t=dfa; 45 for (int i=0;i<len;i++) 46 { 47 if (!t->ch[ord(s[i])]) t->ch[ord(s[i])]=newnode(); 48 t=t->ch[ord(s[i])]; 49 } 50 t->end=1; 51 } 52 inline void buildDfa() 53 { 54 static node * queue[sizeOfMemory]; 55 int l=0, r=0; 56 57 dfa->fail=dfa; 58 for (int i=0;i<sizeOfType;i++) 59 if (!dfa->ch[i]) dfa->ch[i]=dfa; 60 else dfa->ch[i]->fail=dfa, queue[r++]=dfa->ch[i]; 61 62 for ( ;l<r; ) 63 { 64 node * u=queue[l++]; 65 u->end|=u->fail->end; 66 for (int i=0;i<sizeOfType;i++) 67 if (u->ch[i]) 68 { 69 u->ch[i]->fail=u->fail->ch[i]; 70 queue[r++]=u->ch[i]; 71 } 72 else 73 u->ch[i]=u->fail->ch[i]; 74 } 75 } 76 } 77 using namespace trieDfa; 78 79 int cases, n; 80 char str[sizeOfText]; 81 int f[sizeOfText][sizeOfMemory]; 82 inline int min(int x, int y) {return x<y?x:y;} 83 inline int dp(char * ); 84 85 int main() 86 { 87 for (scanf("%d", &n);n;scanf("%d", &n)) 88 { 89 clear(); 90 for (int i=1;i<=n;i++) 91 { 92 scanf("%s", str); 93 insert(str); 94 } 95 buildDfa(); 96 scanf("%s", str); 97 printf("Case %d: %d ", ++cases, dp(str)); 98 } 99 100 return 0; 101 } 102 inline int dp(char * s) 103 { 104 int len=strlen(s); 105 int ret=inf; 106 107 memset(f, inf, sizeof(f)); 108 f[0][0]=0; 109 for (int i=0;i<len;i++) 110 for (int j=0;j<port;j++) 111 for (int k=0;k<sizeOfType;k++) 112 if (!E[j]->ch[k]->end) 113 f[i+1][E[j]->ch[k]->idx]=min(f[i+1][E[j]->ch[k]->idx], f[i][j]+(ord(s[i])!=k)); 114 for (int i=0;i<port;i++) ret=min(ret, f[len][i]); 115 116 return ret==inf?-1:ret; 117 }