zoukankan      html  css  js  c++  java
  • 【hihoCoder 1036】Trie图

    看了一下简单的$Trie图$,调模板调啊调一连调了$2h$,最后发现$-'a'$打成$-'A'$了hhh,有种摔键盘的冲动。

    $Trie图$是$Trie树$上建立“前缀边”,不用再像在$Trie树$上那样顺着$fail$一个一个往上跳了,省了不少时间。这种做法在$hihoCoder$上时间排到了前三名。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define N 1000006
    using namespace std;
    int c[N][26], cnt = 0, fail[N], n, q[N], w[N];
    inline void ins(char *s) {
    	int len = strlen(s), now = 0;
    	for(int i = 0; i < len; ++i) {
    		int t = s[i] - 'a';
    		if (!c[now][t]) c[now][t] = ++cnt;
    		now = c[now][t];
    	}
    	w[now] = 1;
    }
    inline void BFS() {
    	int now, head = -1, tail = -1;
    	for(int t = 0; t < 26; ++t)
    		if (c[0][t])
    			q[++tail] = c[0][t];
    	while (head != tail) {
    		now = q[++head];
    		for(int t = 0; t < 26; ++t)
    			if (!c[now][t])
    				c[now][t] = c[fail[now]][t]; //建立“前缀边”
    			else {
    				q[++tail] = c[now][t];
    				int tmp = fail[now];
    				while(tmp && !c[tmp][t])
    					tmp = fail[tmp];
    				fail[c[now][t]] = c[tmp][t];
    			}
    	}
    }
    inline void AC(char *s) {
    	int len = strlen(s), now = 0;
    	for(int i = 0; i < len; ++i) {
    		now = c[now][s[i] - 'a'];
    		if (w[now]) {
    			puts("YES");
    			return;
    		}
    	}
    	puts("NO");
    }
    int main() {
    	scanf("%d
    ", &n);
    	char s[N];
    	for(int i = 1; i <= n; ++i)
    		scanf("%s", s), ins(s);
    	BFS();
    	scanf("%s", s);
    	AC(s);
    	return 0;
    }
    

    不要介意“前缀边”这个名字起得多么牵强,可以理解为记录$fail$最终跳到的点,直接指过去就行了。gty学长讲课时也讲过这种优化。

  • 相关阅读:
    UVALive4727:jump
    UVALive
    UVA11795 Mega Man's Mission
    UVA4731:Cellular Network
    UVA11404:Palindromic Subsequence
    设计思路
    阅读计划
    上课未完成代码原因
    《人月神话》读后感
    《软件工程》第十一章总结
  • 原文地址:https://www.cnblogs.com/abclzr/p/5355499.html
Copyright © 2011-2022 走看看