• [HNOI2004] L语言


    给定字典和没有标点的文章,求能够被识别的最长前缀。

    显然不能贪心,设(f[i])表示前(i)个字符构成的前缀能否被识别,然后在AC自动机上暴力转移即可。

    具体来说,每走到一个新位置,就沿着fail链把所有能转移的都转移了。

    (突然发现我以前的AC自动机模板好像又有点锅?)

    #include <bits/stdc++.h>
    using namespace std;
    
    const int N = 1000005;
    
    int ch[N][26],dep[N],fi[N],val[N],n,m,t1,t2,t3,t4,ind;
    int f[N];
    
    void ins(char *s) {
    	int len=strlen(s),p=0;
    	for(int i=0;i<len;i++) {
    		if(ch[p][s[i]-'a']==0) ch[p][s[i]-'a']=++ind;
    		p=ch[p][s[i]-'a'];
    		dep[p]=i+1;
    	}
    	val[p]++;
    }
    
    void build() {
    	queue <int> q;
    	for(int i=0;i<26;i++) if(ch[0][i]) q.push(ch[0][i]);
    	while(!q.empty()) {
    		int p=q.front(); q.pop();
    		for(int i=0;i<26;i++)
    			if(ch[p][i]) fi[ch[p][i]]=ch[fi[p]][i],q.push(ch[p][i]);
    			else ch[p][i]=ch[fi[p]][i];
    	}
    }
    
    int query(char *s) {
    	int ans=0,len=strlen(s),p=0;
    	for(int i=0;i<len;i++) {
    		p=ch[p][s[i]-'a'];
    		for(int t=p;t;t=fi[t])
    			if(val[t]) f[i+1]|=f[i+1-dep[t]];
    	}
    	for(int i=1;i<=len;i++) if(f[i]) ans=i;
    	return ans;
    }
    
    char str[N];
    
    int main() {
    	cin>>n>>m;
    	for(int i=1;i<=n;i++) cin>>str,ins(str);
    	build();
    	for(int i=1;i<=m;i++) {
            memset(f,0,sizeof f);
            f[0]=1;
            cin>>str;
            cout<<query(str)<<endl;
    	}
    }
    
    
  • 相关阅读:
    Java的一天学习
    IIS7配置PHP图解
    主流HTML5游戏框架的分析和对比
    HTTP请求
    hibernate -- 数据库连接池的失效检查设置
    mysql备份
    深入探索SOAP1.1--使用SAAJ1.2.1
    JDBC连接执行MySQL存储过程报权限错误
    mysql(connector/ODBC)
    mysql查询优化(三)
  • 原文地址:https://www.cnblogs.com/mollnn/p/12251370.html
Copyright © 2020-2023  润新知