zoukankan      html  css  js  c++  java
  • BZOJ 3507 [CQOI2014]通配符匹配 (哈希 + dp)

    题目链接:https://darkbzoj.tk/problem/3507

    以通配符为分界点将原字符串分开,通配符也算一个字符串
    (dp[j][i]) 表示到第 (j) 个匹配字符串能否匹配到第 (i) 个位置
    分情况转移即可

    #include<bits/stdc++.h>
    using namespace std;
    
    const int maxn = 200010;
    const int M = 998244353;
    const int base = 131;
    
    int N, n;
    int f[maxn], p[maxn];
    int dp[50][maxn];
    
    int v[maxn], l[maxn], cnt = 0;
    
    char A[maxn], s[maxn];
    
    int Get_Hash(int L, int R){
        return ((f[R] - 1ll * f[L - 1] * p[R - L + 1] % M) % M + M) % M; 
    }
    
    int main(){
        p[0] = 1;
        for(int i = 1 ; i <= 200000 ; ++i) p[i] = 1ll * p[i-1] * base % M;
        
        scanf("%s", A + 1);
        int len = strlen(A + 1);
        int le = 0;
    	A[len + 1] = '?'; 
        for(int i = 1 ; i <= len + 1; ++i){
            if(A[i] == '*' || A[i] == '?'){
            	if(f[i - 1] != 0) v[++cnt] = f[i - 1]; l[cnt] = le;
                f[i] = 0; le = 0;
                if(i <= len){
    	            if(A[i] == '*') v[++cnt] = -1;
    	            if(A[i] == '?') v[++cnt] = -2;            	
    			}
    			continue;
            }
            if(i == len + 1) break; 
            f[i] = (1ll * f[i - 1] * base % M + A[i] - 'a' + 1) % M;
            ++le;
        } 
        
        cin >> N;
        while(N--){
            memset(dp, 0, sizeof(dp));
            scanf("%s", s + 1);
            n = strlen(s + 1);
    		
    		f[0] = 0;
            for(int i = 1 ; i <= n ; ++i){
                f[i] = (1ll * f[i - 1] * base % M + s[i] - 'a' + 1) % M;
        	}
            
            dp[0][0] = 1; int la = 0, flag = 0;
            for(int j = 1 ; j <= cnt ; ++j){
            	flag = n + 1;
                for(int i = 0 ; i <= n ; ++i){
                	if(v[j] < 0) {
                		if(i > 0 && v[j] == -2){
                			dp[j][i] = dp[j - 1][i - 1];
                			if(dp[j][i] == 1) flag = min(flag, i);
    					}
    					if(v[j] == -1){
    						if(i >= la) dp[j][i] = 1;
    						if(dp[j][i]) flag = min(flag, i);
    					}
    				}
                	else if(i >= l[j]){
    	                int val = Get_Hash(i - l[j] + 1, i);
    	                if(val == v[j] && dp[j - 1][i - l[j]]) dp[j][i] = 1;
    	                if(dp[j][i]) flag = min(flag, i);
    				}
                }
                la = flag;
            }
            
            if(dp[cnt][n]) printf("YES
    ");
            else printf("NO
    ");
        }
        
        return 0;
    }
    
  • 相关阅读:
    开博的缘由
    听了一节公开课 课后感
    python中的函数、变量和递归函数
    迭代器和生成器
    字符串的格式化
    html和htm的区别
    基本数据类型总结
    数据类型-----集合
    基础测试题(字符串、列表、元组、字典)
    基本数据类型-----字典(Dictionary)
  • 原文地址:https://www.cnblogs.com/tuchen/p/14008029.html
Copyright © 2011-2022 走看看