zoukankan      html  css  js  c++  java
  • 一本通 1475:L语言

    一本通 1475:L语言

    原题链接

    Solution

    AC自动机

    这题一眼看上去就是道 (AC) 自动机题。

    于是快速地把 (AC) 自动机板子打出来,并建好 (trie) 图。

    接下来分析一下题目

    我们用 (vis[i]) 标记一段文章长度为 (i) 的前缀是否可以被表示出来。

    对于一段文章,我们枚举它的前缀,设长度为 (i),然后暴力跳 (fail) 指针,每次判断 (i - End[res] + 1) 是否能够被字典中的单词表示出来。

    • End[i]:(i) 结尾的单词的长度

    • res: 暴力跳前缀的 (fail) 指向的点的编号

    判断时要 (+1) 是因为我们要输出长度,而字符串是从第 0 为开始的,所以 (+1)

    结合代码理解一下吧

    Code

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <queue>
    
    using namespace std;
    
    const int N = 2e6 + 10;
    int n, m;
    char s[13], t[N];
    int End[N];
    int trie[300][27], tot, fail[N];
    bool vis[N];
    //--------------------------------------------AC自动机模板不解释
    void insert(char s[]){
    	int len = strlen(s);
    	int now = 0;
    	for(int i = 0; i < len; i++){
    		int x = s[i] - 'a';
    		if(!trie[now][x]) trie[now][x] = ++tot;
    		now = trie[now][x];
    	}
    	End[now] = len;
    }
    
    void build(){
    	queue <int> q;
    	for(int i = 0; i < 26; i++)
    		if(trie[0][i])
    			q.push(trie[0][i]);
    	while(!q.empty()){
    		int now = q.front();
    		q.pop();
    		for(int i = 0; i < 26; i++){
    			if(trie[now][i]){
    				fail[trie[now][i]] = trie[fail[now]][i];
    				q.push(trie[now][i]);
    			}else trie[now][i] = trie[fail[now]][i];
    		}
    	}
    }
    
    int main(){
    	scanf("%d%d", &n, &m);
    	for(int i = 1; i <= n; i++){
    		scanf("%s", s);
    		insert(s);
    	}
    	build();
    	while(m--){
    		memset(vis, 0, sizeof(vis));
    		vis[0] = 1;			//长度为0的前缀可以被表示出来
    		int ans = 0, now = 0;
    		scanf("%s", t);
    		for(int i = 0; i < strlen(t); i++){
    			now = trie[now][t[i] - 'a'];
    			int res = now;			//res转存一下
    			while(res){
    				if(vis[i - End[res] + 1]){		//判断i - End[res] + 1能否被表示
    					vis[i + 1] = 1;
    					break;
    				}
    				res = fail[res];	//暴力跳fail
    			}
    			if(vis[i + 1])
    				ans = i + 1;
    		}
    		printf("%d
    ", ans);
    	}
    	return 0;
    }
    

    End

    本文来自博客园,作者:xixike,转载请注明原文链接:https://www.cnblogs.com/xixike/p/15109615.html

  • 相关阅读:
    java操作生成jar包 和写入jar包
    jboss配置jndi连接池
    windows 域的LDAP查询相关举例
    LDAP error Code 及解决方法
    HDU 6417
    CF1299D Around the World
    codechef Chef and The Colored Grid
    Educational Codeforces Round 82 (Rated for Div. 2)
    CF1237F Balanced Domino Placements
    CF1254E Send Tree to Charlie
  • 原文地址:https://www.cnblogs.com/xixike/p/15109615.html
Copyright © 2011-2022 走看看