【AC自动机】 HDOJ 2825 Wireless Password

来源:互联网 发布:淘宝双十一h5页面 编辑:程序博客网 时间:2024/05/16 04:42

AC自动机+状态压缩DP。用dp[i][j][k]表示走i步,到达AC自动机中的j节点,含有的字符串k种类(二进制状态压缩),所有的方案数。

#include <iostream>#include <sstream>#include <algorithm>#include <vector>#include <queue>#include <stack>#include <map>#include <set>#include <bitset>#include <cstdio>#include <cstring>#include <cstdlib>#include <cmath>#include <climits>#define maxn 105#define eps 1e-6#define mod 20090717#define INF 99999999#define lowbit(x) (x&(-x))//#define lson o<<1, L, mid//#define rson o<<1 | 1, mid+1, Rtypedef long long LL;typedef unsigned long long ULL;using namespace std;struct node{    int next[maxn][26];    int fail[maxn];    int end[maxn];    char s[maxn];    queue<int> q;    int top, now, root;    int newnode(void)    {        end[top] = 0;        fail[top] = -1;        for(int i = 0; i < 26; i++)            next[top][i] = -1;        return top++;    }    void init(void)    {        top = 0;        root = newnode();    }    void insert(int x)    {        int i, len = strlen(s), k;        now = root;        for(i = 0; i < len; i++) {            k = s[i] - 'a';            if(next[now][k] == -1)                next[now][k] = newnode();            now = next[now][k];        }        end[now] = x;    }    void build(void)    {        int i;        fail[root] = root;        now = root;        for(i = 0; i < 26; i++)            if(next[now][i] == -1)                next[now][i] = root;            else {                fail[next[now][i]] = root;                q.push(next[now][i]);            }        while(!q.empty()) {            now = q.front();            q.pop();end[now] |= end[fail[now]];            for(i = 0; i < 26; i++)                if(next[now][i] == -1)                    next[now][i] = next[fail[now]][i];                else {                    fail[next[now][i]] = next[fail[now]][i];                    q.push(next[now][i]);                }        }    }}trie;int dp[30][105][1100];int is[1100];int n, m, kk;void read(void){    int i, tmp = 1;    trie.init();    for(i = 1; i <= m; i++) {        scanf("%s", trie.s);        trie.insert(tmp);        tmp<<=1;    }    trie.build();}void init(void){    memset(dp, 0, sizeof dp);}void work(void){    int o = 0, i, j, k, ans, tmp, res, cnt, p;    for(i = 0; i < m; i++) o<<=1, o+=1;    dp[0][0][0] = 1;    for(i = 0; i <= n; i++)        for(j = 0; j < trie.top; j++)            for(k = 0; k <= o; k++) {                if(dp[i][j][k] == 0) continue;                for(p = 0; p < 26; p++)                    dp[i+1][trie.next[j][p]][k|trie.end[trie.next[j][p]]] = (dp[i+1][trie.next[j][p]][k|trie.end[trie.next[j][p]]] + dp[i][j][k])%mod;            }    ans = 0;    cnt = 0;    for(i = 0; i <= o; i++) {        tmp = i;        res = 0;        while(tmp) res+=tmp&1, tmp>>=1;        if(res >= kk) is[cnt++] = i;    }    for(i = 0; i < trie.top; i++)        for(j = 0; j < cnt; j++)            ans = (ans + dp[n][i][is[j]])%mod;    printf("%d\n", ans);}int main(void){    while(scanf("%d%d%d", &n, &m, &kk), n!=0 || m!=0 || kk!=0) {                init();        read();        work();    }    return 0;}

后来对程序优化了一下,跑的更快了。

#include <iostream>#include <sstream>#include <algorithm>#include <vector>#include <queue>#include <stack>#include <map>#include <set>#include <bitset>#include <cstdio>#include <cstring>#include <cstdlib>#include <cmath>#include <climits>#define maxn 105#define eps 1e-6#define mod 20090717#define INF 99999999#define lowbit(x) (x&(-x))//#define lson o<<1, L, mid//#define rson o<<1 | 1, mid+1, Rtypedef long long LL;typedef unsigned long long ULL;using namespace std;int next[maxn][26];int fail[maxn];int end[maxn];char s[maxn];int dp[30][105][1100];int hash[1100];int n, m, kk;queue<int> q;int top, now, root;int newnode(void){    end[top] = 0;    fail[top] = -1;    for(int i = 0; i < 26; i++)        next[top][i] = -1;    return top++;}void init(void){    top = 0;    root = newnode();}void insert(int x){    int i, len = strlen(s), k;    now = root;    for(i = 0; i < len; i++) {        k = s[i] - 'a';        if(next[now][k] == -1)            next[now][k] = newnode();        now = next[now][k];    }    end[now] = x;}void build(void){    int i;    fail[root] = root;    now = root;    for(i = 0; i < 26; i++)        if(next[now][i] == -1)            next[now][i] = root;        else {            fail[next[now][i]] = root;            q.push(next[now][i]);        }    while(!q.empty()) {        now = q.front();        q.pop();        end[now] |= end[fail[now]];        for(i = 0; i < 26; i++)            if(next[now][i] == -1)                next[now][i] = next[fail[now]][i];            else {                fail[next[now][i]] = next[fail[now]][i];                q.push(next[now][i]);            }    }}void read(void){    int i, tmp = 1;    for(i = 1; i <= m; i++) {        scanf("%s", s);        insert(tmp);        tmp<<=1;    }    build();}void work(void){    int o = 0, i, j, k, ans, p;    for(i = 0; i < m; i++) o<<=1, o+=1;    for(i = 0; i <= n; i++)        for(j = 0; j < top; j++)            for(k = 0; k <= o; k++)                dp[i][j][k] =0;    dp[0][0][0] = 1;    for(i = 0; i < n; i++)        for(j = 0; j < top; j++)            for(k = 0; k <= o; k++) {                if(dp[i][j][k] == 0) continue;                for(p = 0; p < 26; p++)                    dp[i+1][next[j][p]][k|end[next[j][p]]] = (dp[i+1][next[j][p]][k|end[next[j][p]]] + dp[i][j][k])%mod;            }    ans = 0;    for(i = 0; i <= o; i++)        if(hash[i] >= kk)            for(j = 0; j < top; j++)                ans = (ans + dp[n][j][i])%mod;    printf("%d\n", ans);}int main(void){    int i, j;    for(i = 0; i < (1<<10); i++) {        hash[i] = 0;        for(j = 0; j < 10; j++)            if(i & (1<<j))                hash[i]++;    }    while(scanf("%d%d%d", &n, &m, &kk), n!=0 || m!=0 || kk!=0) {                init();        read();        work();    }    return 0;}


0 0
原创粉丝点击