• 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;
    }
    
  • 相关阅读:
    scoket --- 练习
    网络编程---scoket使用,七层协议,三次挥手建连接,四次挥手断连接
    类的总复习
    面向对象 --- 类的绑定方法,面向对象高阶
    组合,访问限制机制,抽象类 --- 练习
    面向对象 --- 类的组合,封装,多态
    类的继承 --- 练习
    面向对象 --- 类的继承
    基于面向对象设计一个游戏
    请求头类型content-type
  • 原文地址:https://www.cnblogs.com/tuchen/p/14008029.html
Copyright © 2020-2023  润新知