Resource Archiver hdu3247

來源:互聯網
上載者:User

通過這題加深了對trie圖的認識,trie圖建好之後,匹配就不再需要fail指標了,在解決產生串類問題中,由於有禁止的包含的串,一定不能用fail指標進行轉移,否則產生的串中有可能包含禁止串。

 這道題關鍵在bfs求0點和resource串尾節點這些點倆倆之間最小距離,有倆種方法,

第一種是只通過ch來轉移,但這樣求出來的最短路不一定是最短的,因為有些resource串可能是另一些resource串的尾碼,這相當於他們之間的最短路徑是0,而這種情況是沒有被考慮進來的,所以這就要求我們在DP轉移時做文章,詳細見代碼。

第二種是通過ch和fail共同轉移,但是通過fail指標進行轉移時代價為0,而且只修改fail指標指向節點的距離值,但不把節點加入到隊列中,這樣處理完之後,就相當於一個普通的圖了, 剩下的就是一個裸的TSP問題了。


#include <iostream>#include <cstdio>#include <cstdlib>#include <cmath>#include <queue>#include <algorithm>#include <vector>#include <cstring>#include <stack>#include <cctype>#include <utility>   #include <map>#include <string>  #include <climits> #include <set>#include <string>    #include <sstream>#include <utility>   #include <ctime>using std::priority_queue;using std::vector;using std::swap;using std::stack;using std::sort;using std::max;using std::min;using std::pair;using std::map;using std::string;using std::cin;using std::cout;using std::set;using std::queue;using std::string;using std::istringstream;using std::make_pair;using std::getline;using std::greater;using std::endl;using std::multimap;typedef long long LL;typedef unsigned long long ULL;typedef pair<int, int> PAIR;typedef multimap<int, int> MMAP;const int MAXN(60010);const int SIGMA_SIZE(2);const int MAXM(110);const int MAXE(4000010);const int MAXH(18);const int INFI((INT_MAX-1) >> 2);const int MOD(10007);const ULL LIM(1000000000000000ull);int point[12];int que[MAXN];int front, back;struct AC{    int ch[MAXN][SIGMA_SIZE];    int f[MAXN], state[MAXN];    bool val[MAXN];    int size;        void init()    {        memset(ch[0], 0, sizeof(ch[0]));        f[0] = state[0] = 0;        val[0] = false;        size = 1;    }    inline int idx(char temp)    {        return temp-'0';            }        void insert(char *S, bool flag, int num = -1)    {        int u = 0, id;        for(; *S; ++S)        {            id = idx(*S);            if(!ch[u][id])            {                memset(ch[size], 0, sizeof(ch[size]));                val[size] = false;                state[size] = 0;                ch[u][id] = size++;            }            u = ch[u][id];        }        if(!flag){            point[num] = u;state[u] |= (1 << num);  //標記resource串}        val[u] |= flag;    //標記virus串    }      void construct()    {        front = back = 0;        int cur, u;        for(int i = 0; i < SIGMA_SIZE; ++i)        {            u = ch[0][i];            if(u)            {                que[back++] = u;                f[u] = 0;            }        }        while(front < back)        {            cur = que[front++];            for(int i = 0; i < SIGMA_SIZE; ++i)            {                u = ch[cur][i];                if(u)                {                    que[back++] = u;                    f[u] = ch[f[cur]][i];state[u] |= state[f[u]];                    val[u] |= val[f[u]];                }                else                    ch[cur][i] = ch[f[cur]][i];            }        }    }};AC ac;void bfs(int s, int *dist)  //求0點和所有resource串結尾節點之間最短路徑{    for(int i = 0; i < ac.size; ++i)        dist[i] = INFI;    dist[point[s]] = 0;front = back = 0;que[back++] = point[s];int cur, tv;    while(front < back)    {       cur = que[front++];   tv = ac.ch[cur][0];   //注意此處只能通過ch進行轉移 //如果通過fail指標轉移則只能修改點權,但不能將其入隊,如果將其入隊,可能會導致 //訪問路徑中出現非法串   if(!ac.val[tv] && dist[tv] == INFI)   {   dist[tv] = dist[cur]+1;   que[back++] = tv;   }   tv = ac.ch[cur][1];   if(!ac.val[tv] && dist[tv] == INFI)   {   dist[tv] = dist[cur]+1;   que[back++] = tv;   }    }}int dist[12][MAXN];char str[1010];int table[12][1 << 11]; void solve(int n){    int lim = (1 << (n+1))-1;    for(int i = 0; i <= n; ++i)        for(int j = 0; j <= lim; ++j)            table[i][j] = INFI;    table[0][1] = 0;    for(int i = 1; i < lim; ++i)    {        for(int j = 0; j <= n; ++j)if((i&(1 << j)) && table[j][i] != INFI)for(int k = 0; k <= n; ++k){int ts = i|ac.state[point[k]];   //到達一個節點後,可能有多個串被同時訪問table[k][ts] = min(table[k][ts], table[j][i]+dist[j][point[k]]);}    }    int ans = INFI;    for(int i = 0; i <= n; ++i)        ans = min(ans, table[i][lim]);    printf("%d\n", ans);}int main(){    int n, m;    while(scanf("%d%d", &n, &m), n+m)    {        ac.init();        point[0] = 0;        for(int i = 1; i <= n; ++i)        {            scanf("%s", str);      //resource            ac.insert(str, false, i);        }        for(int i = 0; i < m; ++i)        {            scanf("%s", str);      //virus            ac.insert(str, true);        }        ac.construct();        for(int i = 0; i <= n; ++i)            bfs(i, dist[i]);        solve(n);    }    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.