hdu 2825 AC自動機+狀壓dp

來源:互聯網
上載者:User
Wireless Password題意:給m個串(m<=10),求長度為n且至少含k個可重疊給定串的串的數目。AC自動機+狀壓dp,i為串長,j為二進位狀態,表示當前包含哪些串,k為trie樹上一節點編號。
#include <iostream>#include <cstdio>#include <cstring>#include <vector>#include <queue>using namespace std;#define mod 20090717#define pb push_back#define lowbit(x) ((x)&(-x))struct node{    int son[26],fail;    int cnt;//二進位狀態,標記包括自己和前面,有哪些給定字串    node(){memset(son,0,sizeof(son));fail=0;cnt=0;}};vector<node> ac;int hash[256];int dp[30][1<<11][110];int n,m,K;int map[1<<11];//預先處理出位元中1的個數void init() {    memset(map,0,sizeof(map));    for(int i=0;i<(1<<10);++i) {        map[i]=map[i>>1]+(i&1);    }    for(int i=0;i<26;++i) hash['a'+i]=i;}void insert(const char *str,int num) {    int p=0,i=0;    while(str[p]) {        if(!ac[i].son[hash[str[p]]]) {            ac[i].son[hash[str[p]]]=ac.size();            ac.pb(node());        }        i=ac[i].son[hash[str[p]]];        ++p;    }    ac[i].cnt=1<<num;}void getFail() {    queue<int> qu;    qu.push(0);    while(!qu.empty()) {        int cur=qu.front();qu.pop();        for(int i=0;i<26;++i) {            int nex=ac[cur].son[i];            int p=ac[cur].fail;//            while(~p&&!ac[p].son[i]) p=ac[p].son[i];//這部沒必要,淺層節點必有兒子            if(nex) {                qu.push(nex);                if(~p) ac[nex].fail=ac[p].son[i],ac[nex].cnt|=ac[ac[p].son[i]].cnt;                else ac[nex].fail=0;            }            else {                if(~p) ac[cur].son[i]=ac[p].son[i];//空兒子不是指向根,就是指向實兒子            }        }    }}int main() {    ios::sync_with_stdio(false);    init();    while(cin >> n >> m >> K,n||m||K) {        ac.clear();        ac.pb(node());        ac[0].fail=-1;        for(int i=0;i<m;++i) {            char str[20];            cin >> str;            insert(str,i);        }        getFail();//        memset(dp,0,sizeof(dp));//dp數組太大,全部清0太耗時        for(int i=0;i<=n;++i)            for(int j=0;j<(1<<m);++j)                for(int k=0;k<ac.size();++k)                    dp[i][j][k]=0;        dp[0][0][0]=1;        int ans=0;        for(int i=0;i<n;++i)            for(int j=0;j<(1<<m);++j)                for(int k=0;k<ac.size();++k) {                    if(!dp[i][j][k]) continue;                    for(int p=0;p<26;++p) {                        int spos=ac[k].son[p],sta=j|ac[spos].cnt;                        dp[i+1][sta][spos]+=dp[i][j][k];                        dp[i+1][sta][spos]%=mod;                    }                }        for(int i=0;i<(1<<m);++i)            for(int j=0;j<ac.size();++j)                if(map[i]>=K) {ans+=dp[n][i][j];ans%=mod;}//這裡不要忘記模數        cout << ans << endl;    }    return 0;}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.