zoukankan      html  css  js  c++  java
  • 国庆集训Day1T1撰写博客

    国庆集训Day1T1撰写博客

    题目

    http://noip.ybtoj.com.cn/contest/584/problem/1

    给定长度为(n)的字符串(s)(m)个字符串(t),将(s)中的第(i)个字符替换成空格的代价为(a_i),求使(s)中不出现任何一个(t)的最小代价.

    image-20211108095227972

    思路

    (f_i)表示处理完(s)的前(i)个字符的最小代价.

    则有(f_0=0).

    转移((pre_i)表示存在字符串(t) ,(t)(s)的字串(s_{pre_ildots i})相等,且(pre_i)最小,若不存在,(pre_i=0)):

        memset(f, 0x3f, sizeof(f));
        f[0] = 0;
        for (int i = 1; i <= n; i++) {
            int boundary = pre[i];
            for (int j = i; j >= boundary; j--) {
                boundary = max(boundary, pre[j]);
                f[i] = min(f[i], f[j - 1] + val[j]);
            }
        }
        cout << f[n];
    

    注意到对于每一个(i),最终(j)的下届((boundary))都是确定的,且是递增的,且状态转移方程中每一项都只和(i,j)中的一个有关,符合单调队列优化条件.

    故单调队列优化后可以做到(O(n)).

    代码

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    
    typedef unsigned long long ull;
    
    const int N = 2e5 + 10 ,  M = 15;
    
    const ull mod1 = 1e9 + 7 , base1 = 1331;
    const ull mod2 = 1e6 + 7 , base2 = 131;
    
    int read() {
    	int re = 0;
    	char c = getchar();
    	while(c < '0' || c > '9')c = getchar();
    	while(c >= '0' && c <= '9')re = (re << 1) + (re << 3) + c - '0' , c =getchar();
    	return re;
    }
    char readc() {
    	char c = getchar();
    	while(c < 'a' || c > 'z')c = getchar();
    	return c;
    }
    int n , m;
    int val[N];
    int pre[N];
    int f[N];
    
    struct MQueue {
    	int head , tail;
    	int j[N] , f[N];
    	void pop(int boundary) {
    		while(head < tail && j[head] < boundary)++head;
    	}
    	void push(int j_ , int f_) {
    		while(head < tail && f[tail - 1] >= f_)--tail;
    		j[tail] = j_ , f[tail] = f_;
    		++tail;
    	}
    	int front() {
    		return head == tail ? 1e9 : f[head];
    	}
    } mQue;
    
    namespace input {
    	char s[N] , t[15][N];
    	int len[15];
    	template <ull base , ull mod>
    	ull GetValue (int l , int r) {
    		static ull p[N] , val[N] ;
    		static bool vis = false;
    		if(!vis) {
    			vis = true;
    			p[0] = 1;
    			for(int i = 1 ; i <= n ; i++)
    				p[i] = p[i - 1] * base % mod , val[i] = val[i - 1] * base % mod + s[i] ;
    		}
    		return (val[r] - val[l - 1] *  p[r - l + 1] % mod + mod) % mod;
    	}
    	void input() {
    		n = read() , m = read();
    		for(int i = 1 ; i <= n ; i++)s[i] = readc();
    		for(int i = 1 ; i <= n ; i++)val[i] = read();
    		for(int i = 1 ; i <= m ; i++) {
    			ull v1 = 0 , v2 = 0;
    			t[i][len[i] = 1] = readc();
    			do
    				t[i][++len[i]] = getchar();
    			while(t[i][len[i]] >= 'a' && t[i][len[i]] <= 'z');
    			--len[i];
    
    			for(int j = 1 ; j <= len[i] ; j++)
    				v1 = (v1 * base1 + t[i][j]) % mod1 , v2 = (v2 * base2 + t[i][j]) % mod2;
    
    			for(int j = 1 ; j + len[i] - 1 <= n ; j++)
    				if(v1 == GetValue<base1 , mod1>(j , j + len[i] - 1) && v2 == GetValue<base2 , mod2>(j , j + len[i] - 1))
    					pre[j + len[i] - 1] = max(pre[j + len[i] - 1] , j);
    		}
    
    	}
    }
    
    int main() {
    	freopen("wzadx.in" , "r" , stdin);
    	freopen("wzadx.out"  ,"w" , stdout);
    
    	input::input();
    
    	memset(f , 0x3f , sizeof(f));
    	f[0] = 0 , mQue.push(0 , f[0]);
    	int boundary = 0;
    	for(int i = 1 ; i <= n ; i++) {
    		boundary = max(pre[i] , boundary);
    		mQue.push(i , f[i - 1] + val[i]);
    		mQue.pop(boundary);
    		f[i] = min(f[i] , mQue.front());
    	}
    	cout << f[n];
    	return 0;
    }
    
  • 相关阅读:
    64位系统下,一个32位的程序究竟可以申请到多少内存,4GB还是更多
    selenium3 + python3
    selenium3 + python
    selenium3 + python
    selenium3+python-多窗口、句柄(handle)
    selenium3 + python
    selenium3 + python
    selenium3 + python 操作浏览器基本方法
    Appium
    Appium
  • 原文地址:https://www.cnblogs.com/dream1024/p/15522937.html
Copyright © 2011-2022 走看看