zoukankan      html  css  js  c++  java
  • CF701F String set queries (分块思想+暴力)

    很容易想到AC自动机,但是却发现不怎么支持删除

    完蛋,怎么办?

    思考如何优化暴力

    有两种暴力:一种是kmp,一种是trie

    trie时间复杂度优秀,但空间不行;

    kmp时间不行

    那么我们可以互补一下

    对于长度小于 (sqrt) 的,我们加入 (trie) 中,否则暴力 (kmp),这样能够维持时间复杂度,因为总长不大

    分块思想真妙!

    #include <map>
    #include <set>
    #include <ctime>
    #include <queue>
    #include <stack>
    #include <cmath>
    #include <vector>
    #include <bitset>
    #include <cstdio>
    #include <cctype>
    #include <string>
    #include <numeric>
    #include <cstring>
    #include <cassert>
    #include <climits>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    #include <functional>
    using namespace std ;
    //#define int long long
    #define rep(i, a, b) for (int i = (a); i <= (b); i++)
    #define per(i, a, b) for (int i = (a); i >= (b); i--)
    #define loop(s, v, it) for (s::iterator it = v.begin(); it != v.end(); it++)
    #define cont(i, x) for (int i = head[x]; i; i = e[i].nxt)
    #define clr(a) memset(a, 0, sizeof(a))
    #define ass(a, sum) memset(a, sum, sizeof(a))
    #define lowbit(x) (x & -x)
    #define all(x) x.begin(), x.end()
    #define ub upper_bound
    #define lb lower_bound
    #define pq priority_queue
    #define mp make_pair
    #define pb push_back
    #define fi first
    #define se second
    #define iv inline void
    #define enter cout << endl
    #define siz(x) ((int)x.size())
    #define file(x) freopen(#x".in", "r", stdin),freopen(#x".out", "w", stdout)
    typedef long long ll ;
    typedef unsigned long long ull ;
    typedef pair <int, int> pii ;
    typedef vector <int> vi ;
    typedef vector <pii> vii ;
    typedef queue <int> qi ;
    typedef queue <pii> qii ;
    typedef set <int> si ;
    typedef map <int, int> mii ;
    typedef map <string, int> msi ;
    const int N = 300010 ;
    const int Sqrt = 500 ;
    const int M = N / Sqrt + 10 ;
    const int INF = 0x3f3f3f3f ;
    const int iinf = 1 << 30 ;
    const ll linf = 2e18 ;
    const int MOD = 1000000007 ;
    const double eps = 1e-7 ;
    void print(int x) { cout << x << endl ; exit(0) ; }
    void PRINT(string x) { cout << x << endl ; exit(0) ; }
    void douout(double x){ printf("%lf
    ", x + 0.0000000001) ; }
    template <class T> void chmin(T &a, T b) { if (a > b) a = b ; }
    template <class T> void chmax(T &a, T b) { if (a < b) a = b ; }
    void upd(int &a, int b) { (a += b) %= MOD ; }
    void mul(int &a, int b) { a = 1ll * a * b % MOD ; }
    
    char s[N] ;
    string st[M] ;
    int cost[M] ;
    int trie[N][29], value[N], nxt[N] ;
    int Q, op, tot = 1, cnt, len ;
    
    signed main(){
    //	freopen("test.in", "r", stdin) ;
    //	freopen("test.out", "w", stdout) ;
    	scanf("%d", &Q) ;
    	while (Q--) {
    		scanf("%d %s", &op, s) ;
    		len = strlen(s) ;
    		if (op < 3) {
    			if (len <= Sqrt) {
    				int now = 1 ;
    				rep(i, 0, len - 1) {
    					int c = s[i] - 'a' ;
    					if (!trie[now][c]) trie[now][c] = ++tot ;
    					now = trie[now][c] ;
    				}
    				value[now] += 3 - 2 * op ;
    			} else {
    				st[cnt] = "" ;
    				rep(j, 0, len - 1) st[cnt] += s[j] ;
    				st[cnt] += '{' ;
    				cost[cnt] = 3 - 2 * op ;
    				cnt++ ;
    			}
    		} else {
    			ll ans = 0 ;
    			rep(j, 0, len - 1) {
    				int now = 1 ;
    				rep(k, j, len - 1) {
    					int c = s[k] - 'a' ;
    					if (!trie[now][c]) break ;
    					now = trie[now][c] ;
    					ans += value[now] ;
    				}
    			}
    		//	cout << ans << endl ;
    			rep(id, 0, cnt - 1) {
    				int Len = siz(st[id]) - 1 ; // 有一个结尾符
    				if (Len > len) continue ;
    				nxt[1] = 0 ;
    				for (int i = 2, j = 0; i <= Len; i++) {
    					while (j && st[id][i - 1] != st[id][j]) j = nxt[j] ;
    					if (st[id][i - 1] == st[id][j]) j++ ;
    					nxt[i] = j ;
    				}
    				for (int i = 1, j = 0; i <= len; i++) {
    					while (j && s[i - 1] != st[id][j]) j = nxt[j] ;
    					if (s[i - 1] == st[id][j]) j++ ;
    					if (j == Len) ans += cost[id] ;
    				}
    			}
    			cout << ans << endl ;
    		}
    	}
    	return 0 ;
    }
    
    /*
    写代码时请注意:
    	1.ll?数组大小,边界?数据范围?
    	2.精度?
    	3.特判?
    	4.至少做一些
    思考提醒:
    	1.最大值最小->二分?
    	2.可以贪心么?不行dp可以么
    	3.可以优化么
    	4.维护区间用什么数据结构?
    	5.统计方案是用dp?模了么?
    	6.逆向思维?
    */
    
    
    
    
    加油ヾ(◍°∇°◍)ノ゙
  • 相关阅读:
    May 1 2017 Week 18 Monday
    April 30 2017 Week 18 Sunday
    April 29 2017 Week 17 Saturday
    April 28 2017 Week 17 Friday
    April 27 2017 Week 17 Thursday
    April 26 2017 Week 17 Wednesday
    【2017-07-04】Qt信号与槽深入理解之一:信号与槽的连接方式
    April 25 2017 Week 17 Tuesday
    April 24 2017 Week 17 Monday
    为什么丑陋的UI界面却能创造良好的用户体验?
  • 原文地址:https://www.cnblogs.com/harryhqg/p/10548925.html
Copyright © 2011-2022 走看看