• 洛谷 P2292 [HNOI2004]L语言


    洛谷 P2292 [HNOI2004]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/15109594.html

  • 相关阅读:
    web移动端开发经验总结
    《前端JavaScript面试技巧》笔记一
    《SEO在网页制作中的应用》视频笔记
    web前端开发笔记(2)
    OAuth2.0理解和用法
    基于hdfs文件创建hive表
    kafka 配置事项
    centos7时间同步
    lambda架构
    hbase hadoop版本
  • 原文地址:https://www.cnblogs.com/xixike/p/15109594.html
Copyright © 2020-2023  润新知