ACM模板整理
来源:互联网 发布:qq for mac历史版本 编辑:程序博客网 时间:2024/05/21 08:36
字符串处理
字典树Trie
/* 字典树Trie */struct Trie { // 最大节点数:模式串个数 * 最大串长度 static const int MAX_NODE = 10000 * 50 + 50; static const int CHAR_SET = 26; // 字符集的大小,也是Trie树中每个节点所连的最大边数 static const int BASE = 'a'; int n; // trie大小 int id[BASE+CHAR_SET+1]; // 字符->int int tag[MAX_NODE]; // 标记,根据需要调整 int trie[MAX_NODE][CHAR_SET]; void init() { for (int i=0;i<CHAR_SET;++i) id[BASE+i] = i; n = 1; memset(trie[0], -1, sizeof(trie[0])); memset(tag, 0, sizeof(tag)); } // 添加一个单词 void add(const char *s) { int p = 0; while (*s) { int i = id[*s]; if (trie[p][i] == -1) { memset(trie[n], -1, sizeof(trie[n])); trie[p][i] = n++; } ++s; p = trie[p][i]; tag[p]++; } } // 在字典中查询以s为前缀的单词个数 int Search(char * s) { int p = 0; while (*s) { int i = id[*s]; if (trie[p][i] == -1) break; ++s; p = trie[p][i]; } if (*s) return 0; else return tag[p]; }};AC自动机
/* AC自动机 解决多模式串匹配问题 * 边:值为一个字符 * 节点:值L(v)={从根节点到v的路径上所有边的值的序列} * 根节点为空,代表初始状态。每个模式串pi都可以找到L(v) = pi。 * fail函数: 如果L(q) 是 L(v) 的一个最长后缀 则 fail(v)=q * 时间复杂度: O(n+m+z) n:模式串总长度 m:文本长 z:文本中模式串出现次数 */struct ACAutomation { // 最大节点数:模式串个数 * 最大串长度 static const int MAX_NODE = 10000 * 50 + 50; static const int CHAR_SET = 26; static const int BASE = 'a'; int n; // trie大小 int id[BASE+CHAR_SET+1]; // 字符->int int tag[MAX_NODE]; // 标记,根据需要调整 int last[MAX_NODE]; // 后缀链接,链接到上一个单词节点 int fail[MAX_NODE]; int trie[MAX_NODE][CHAR_SET]; void init() { for (int i=0;i<CHAR_SET;++i) id[BASE+i] = i; n = 1; memset(trie[0], -1, sizeof(trie[0])); memset(tag, 0, sizeof(tag)); memset(last, 0, sizeof(last)); } void add(const char *s) { int p = 0; while (*s) { int i = id[*s]; if (trie[p][i] == -1) { memset(trie[n], -1, sizeof(trie[n])); trie[p][i] = n++; } ++s; p = trie[p][i]; } //tag[p] = 1; tag[p]++; } void build() { queue<int> Q; fail[0] = 0; int u, v; for (int i=0;i<CHAR_SET;++i) { u = trie[0][i]; if (u != -1) { fail[u] = 0; Q.push(u); } else trie[0][i] = 0; } while (!Q.empty()) { int fr = Q.front();Q.pop(); for (int i=0;i<CHAR_SET;++i) { int &u = trie[fr][i]; // 注意这里使用了一个引用 if ( u != -1 ) { Q.push(u); fail[u] = trie[fail[fr]][i]; last[u] = tag[fail[u]] ? fail[u] : last[fail[u]]; } else u = trie[fail[fr]][i]; } } } // // 已经把所有指向“不存在”的边指向了合适的位置 // 每次在自动机上做一次转移即可 // 例子:hdu2222 统计出现过的关键词,在找到一个关键词后将清除tag标记 int search(const char * T, int len) { int p = 0; int ret = 0; for (int i=0;i<len;++i) { //cout << "on " << T[i] << endl; if (T[i] < 'a' || T[i] > 'z') { p = 0; continue; } int c = id[T[i]]; p = trie[p][c]; int v = last[p]; // 检查当前节点是否是单词 if (tag[p]) {ret += tag[p];tag[p] = 0;} // 沿着后缀链接走, 检查是否为单词 while (v) { if (tag[v]) { ret += tag[v]; tag[v] = 0; } v = last[v]; } //cout << "match on node: " << p << " cnt: " << ret << endl; } return ret; }};KMP
// KMP <span style="font-size:18px;">单模式串查找</span>// T:Text P:patternstruct KMP{ // 构造失配函数 void getFail(const char *P, int *F) { int len = strlen(P); F[0] = 0; F[1] = 0; REP(i, 1, len-1) { int j = F[i]; while(j & P[j] != P[i]) j = F[j]; F[i+1] = P[i] == P[j] ? j+1 : 0; } } // 查找模式串在文本中的出现次数 int find(const char * T, const char *P, int *f) { int n = strlen(T), m = strlen(P); getFail(P, f); int j = 0; int num = 0; REP(i, 0, n-1) { while(j && P[j] != T[i]) j = f[j]; if (P[j] == T[i]) ++j; // 当完成了一个匹配后 状态是肯定要转移一次的 // 因为字符串的最后有 '\0' 所以不用显示写出来(在下一次调用失配函数的时候顺带完成) // 但如果是整数列 则要显示地调用一次失配函数 j = f[j] if (j == m) ++num; } return num; }};
0 0
- ACM模板整理
- ACM模板(个人代码集整理)(持续更新)
- ACM模板整理(精心准备,持续更新中)
- acm模板
- acm模板
- ACM模板
- ACM模板
- ACM 模板
- ACM 模板
- acm 模板
- ACM模板
- ACM 模板
- ACM模板
- ACM模板
- ACM模板
- ACM---模板
- acm 模板
- ACM模板
- 最好的朋友
- 秒杀Xsser.me的渗透工具Beef
- UVA 10881 Piotr's Ants
- [LeetCode] Find Peak Element
- 使用c# 5分钟 创建一个Roguelike 游戏
- ACM模板整理
- Python text file processing
- C#显示时间怎么变成24小时制的
- 【Matlab】 RGB照片转化成灰度图叠加显示
- 杭电ACM1004Let the Balloon Rise
- mybatis返回List<Object[]>数据
- GifView——Android显示GIF动画的扩展控件
- shell——tr的用法
- 2014.12.16窗口适应屏幕大小