zoukankan      html  css  js  c++  java
  • 洛谷 P2292 [HNOI2004]L语言(AC自动机,dp)

    传送门


    解题思路

    设dp[i]为先i位能否被理解。

    然后在AC自动机上匹配,若 num[j]&&dp[i-cnt[j]] 则 dp[i] 等于 1。(j为不断fail的指针)

    AC代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    #include<queue>
    #include<map>
    using namespace std;
    const int maxn=305;
    const int maxm=2e6+5;
    int tr[maxn][30],dp[maxm],cnt[maxn],tot,num[maxn],fail[maxn],n,m;
    string s;
    void insert(string s){
    	int now=0,len=s.length();
    	for(int i=0;i<len;i++){
    		int k=s[i]-'a';
    		if(!tr[now][k]) tr[now][k]=++tot;
    		now=tr[now][k];
    	}
    	cnt[now]=len;
    	num[now]++;
    }
    void build(){
    	queue<int> q;
    	for(int i=0;i<26;i++){
    		if(tr[0][i]) q.push(tr[0][i]);
    	}
    	while(!q.empty()){
    		int now=q.front();q.pop();
    		for(int i=0;i<26;i++){
    			if(tr[now][i]){
    				fail[tr[now][i]]=tr[fail[now]][i];
    				q.push(tr[now][i]);
    			}else{
    				tr[now][i]=tr[fail[now]][i];
    			}
    		}
    	}
    }
    int query(string s){
    	memset(dp,0,sizeof(dp));
    	dp[0]=1;
    	int now=0,len=s.length();
    	for(int i=0;i<len;i++){
    		now=tr[now][s[i]-'a'];
    		for(int j=now;j;j=fail[j]){
    			if(num[j]&&dp[i-cnt[j]+1]){
    				dp[i+1]=1;
    				break;
    			}
    		}
    	}
    	for(int i=len;i>=0;i--){
    		if(dp[i]) return i;
    	}
    }
    int main(){
    	//freopen(".in","r",stdin);
    	//freopen(".out","w",stdout);
    	ios::sync_with_stdio(false);
    	cin>>n>>m;
    	for(int i=1;i<=n;i++) cin>>s,insert(s);
    	build();
    	for(int i=1;i<=m;i++) cin>>s,cout<<query(s)<<endl;
    	return 0;
    }
    
  • 相关阅读:
    求逆元算法
    Almost Sorted Array
    最长不递减子序列
    (LIS)最长上升序列(DP+二分优化)
    rabbitmq延迟消息
    oracle 视图
    oracle 存储过程
    http 会话(session)详解
    系统测试
    Fiddler 手机抓包
  • 原文地址:https://www.cnblogs.com/yinyuqin/p/15394955.html
Copyright © 2011-2022 走看看