设为首页 加入收藏

TOP

uva 1399 - Puzzle(AC自动机)
2015-07-20 17:46:38 来源: 作者: 【 】 浏览:1
Tags:uva 1399 Puzzle 动机

题目链接:uva 1399 - Puzzle

题目大意:给定K和N,表示有K种不同的字符,N个禁止串,求一个最长的串使得该串不包含任何禁止串为子串。如果存在循环或者不能构成的话,输出No。

解题思路:建立AC自动机,然后在AC自动机上做dp,所有单词结尾节点为禁止点。

#include 
   
     #include 
    
      #include 
     
       #include 
      
        using namespace std; const int maxn = 50005; const int sigma_size = 26; struct Aho_Corasick { int sz, ac[maxn][sigma_size]; int fail[maxn], last[maxn]; void init(); int idx(char ch); void insert(char* s); void get_fail(); }fuck; int K, vis[maxn], dp[maxn], jump[maxn]; int dfs (int u) { if (vis[u]) return -1; if (dp[u] != -1) return dp[u]; vis[u] = 1; int& ret = dp[u]; jump[u] = -1; ret = 0; for (int i = K - 1; i >= 0; i--) { int v = fuck.ac[u][i]; if (fuck.last[v] == 0) { int tmp = dfs(v); if (tmp == -1) return -1; if (tmp + 1 > ret) { ret = tmp + 1; jump[u] = i; } } } vis[u] = 0; return ret; } void put_ans (int u) { while (jump[u] != -1) { printf("%c", 'A' + jump[u]); u = fuck.ac[u][jump[u]]; } printf("\n"); } int main () { int cas, n; char word[55]; scanf("%d", &cas); while (cas--) { fuck.init(); memset(vis, 0, sizeof(vis)); memset(dp, -1, sizeof(dp)); scanf("%d%d", &K, &n); for (int i = 0; i < n; i++) { scanf("%s", word); fuck.insert(word); } fuck.get_fail(); if (dfs(0) != -1 && dp[0]) put_ans(0); else printf("No\n"); } return 0; } void Aho_Corasick::init() { sz = 1; memset(ac[0], 0, sizeof(ac[0])); } int Aho_Corasick::idx(char ch) { return ch - 'A'; } void Aho_Corasick::insert(char* s) { int n = strlen(s), u = 0; for (int i = 0; i < n; i++) { int v = idx(s[i]); if (ac[u][v] == 0) { memset(ac[sz], 0, sizeof(ac[sz])); last[sz] = 0; ac[u][v] = sz++; } u = ac[u][v]; } last[u] = 1; } void Aho_Corasick::get_fail () { queue
       
         que; fail[0] = 0; for (int i = 0; i < sigma_size; i++) { int u = ac[0][i]; if (u) { fail[u] = 0; que.push(u); } } while (!que.empty()) { int r = que.front(); que.pop(); for (int i = 0; i < K; i++) { int u = ac[r][i]; if (u == 0) { ac[r][i] = ac[fail[r]][i]; continue; } que.push(u); int v = fail[r]; while (v && ac[v][i] == 0) v = fail[v]; fail[u] = ac[v][i]; last[u] |= last[fail[u]]; } } }
       
      
     
    
   
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇Codeforces 347 B Fixed Points .. 下一篇va_start、va_arg、va_end、va_co..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容:

·C语言中如何将结构体 (2025-12-24 22:20:09)
·纯C语言结构体成员变 (2025-12-24 22:20:06)
·C语言中,指针函数和 (2025-12-24 22:20:03)
·哈希表 - 菜鸟教程 (2025-12-24 20:18:55)
·MySQL存储引擎InnoDB (2025-12-24 20:18:53)