zoukankan      html  css  js  c++  java
  • P4770 [NOI2018]你的名字 [后缀自动机,线段树合并]

    对长串做个后缀自动机上线段树合并,然后你对每个短串搞个SAM在长串后缀自动机上跑。

    答案就是 (sum max(0, len_i - max(len_fa_i, endmax_{pos_i})))
    (pos_i) 指的是 (i) 节点对应原字符串的位置。

    // clang-format off
    // powered by c++11
    // by Isaunoya
    #include<bits/stdc++.h>
    #define rep(i,x,y) for(register int i=(x);i<=(y);++i)
    #define Rep(i,x,y) for(register int i=(x);i>=(y);--i)
    using namespace std;
    using db=double;
    using ll=long long;
    using uint=unsigned int;
    using ull=unsigned long long;
    using pii=pair<int,int>;
    #define Tp template
    #define fir first
    #define sec second
    Tp<class T>void cmax(T&x,const T&y) {
    		if(x<y)x=y;
    }
    Tp<class T>void cmin(T&x,const T&y) {
    		if(x>y)x=y;
    }
    #define all(v) v.begin(),v.end()
    #define sz(v) ((int)v.size())
    #define pb emplace_back
    Tp<class T>void sort(vector<T>&v) {
    		sort(all(v));
    }
    Tp<class T>void reverse(vector<T>&v) {
    		reverse(all(v));
    }
    Tp<class T>void unique(vector<T>&v) {
    		sort(all(v)),v.erase(unique(all(v)),v.end());
    }
    inline void reverse(string&s) {
    	reverse(s.begin(),s.end());
    }
    const int SZ=1<<23|233;
    struct FILEIN {
    	char qwq[SZ],*S=qwq,*T=qwq,ch;
    #ifdef __WIN64
    #define GETC getchar
    #else
    	inline char GETC() {
    		return(S==T)&&(T=(S=qwq)+fread(qwq,1,SZ,stdin),S==T)?EOF:*S++;
    	}
    #endif
    	inline FILEIN&operator>>(char&c) {
    		while(isspace(c=GETC()));
    		return*this;
    	} inline FILEIN&operator>>(string&s) {
    		s.clear();
    		while(isspace(ch=GETC()));
    		if(!~ch)return*this;
    		s=ch;
    		while(!isspace(ch=GETC())&&~ch)s+=ch;
    		return*this;
    	}
    	inline FILEIN&operator>>(char*str) {
    		char*cur=str;
    		while(*cur)*cur++=0;
    		cur=str;
    		while(isspace(ch=GETC()));
    		if(!~ch)return*this;
    		*cur=ch;
    		while(!isspace(ch=GETC())&&~ch)*++cur=ch;
    		*++cur=0;
    		return*this;
    	}
    	Tp<class T>inline void read(T&x) {
    			bool f=0;
    			while((ch=GETC())<48&&~ch)f^=(ch==45);
    			x=~ch?(ch^48):0;
    			while((ch=GETC())>47)x=x*10+(ch^48);
    			x=f?-x:x;
    	}
    	inline FILEIN&operator>>(int&x) {
    		return read(x),*this;
    	} inline FILEIN&operator>>(ll&x) {
    		return read(x),*this;
    	} inline FILEIN&operator>>(uint&x) {
    		return read(x),*this;
    	} inline FILEIN&operator>>(ull&x) {
    		return read(x),*this;
    	}
    	inline FILEIN&operator>>(double&x) {
    		read(x);
    		bool f=x<0;
    		x=f?-x:x;
    		if(ch^'.')return*this;
    		double d=0.1;
    		while((ch=GETC())>47)x+=d*(ch^48),d*=.1;
    		return x=f?-x:x,*this;
    	}
    } in;
    struct FILEOUT {
    	const static int LIMIT=1<<22;
    	char quq[SZ],ST[233];
    	int sz,O,pw[233];
    	FILEOUT() {
    		set(7);
    		rep(i,pw[0]=1,9)pw[i]=pw[i-1]*10;
    	}~FILEOUT() {
    		flush();
    	}
    	inline void flush() {
    		fwrite(quq,1,O,stdout),fflush(stdout),O=0;
    	}
    	inline FILEOUT&operator<<(char c) {
    		return quq[O++]=c,*this;
    	} inline FILEOUT&operator<<(string str) {
    		if(O>LIMIT)flush();
    		for(char c:str)quq[O++]=c;
    		return*this;
    	}
    	inline FILEOUT&operator<<(char*str) {
    		if(O>LIMIT)flush();
    		char*cur=str;
    		while(*cur)quq[O++]=(*cur++);
    		return*this;
    	}
    	Tp<class T>void write(T x) {
    			if(O>LIMIT)flush();
    			if(x<0) {
    				quq[O++]=45;
    				x=-x;
    			}
    			do {
    				ST[++sz]=x%10^48;
    				x/=10;
    			} while(x);
    			while(sz)quq[O++]=ST[sz--];
    	}
    	inline FILEOUT&operator<<(int x) {
    		return write(x),*this;
    	} inline FILEOUT&operator<<(ll x) {
    		return write(x),*this;
    	} inline FILEOUT&operator<<(uint x) {
    		return write(x),*this;
    	} inline FILEOUT&operator<<(ull x) {
    		return write(x),*this;
    	}
    	int len,lft,rig;
    	void set(int l) {
    		len=l;
    	} inline FILEOUT&operator<<(double x) {
    		bool f=x<0;
    		x=f?-x:x,lft=x,rig=1.*(x-lft)*pw[len];
    		return write(f?-lft:lft),quq[O++]='.',write(rig),*this;
    	}
    } out;
    #define int long long
    struct Math {
    	vector<int>fac,inv;
    	int mod;
    	void set(int n,int Mod) {
    		fac.resize(n+1),inv.resize(n+1),mod=Mod;
    		rep(i,fac[0]=1,n)fac[i]=fac[i-1]*i%mod;
    		inv[n]=qpow(fac[n],mod-2);
    		Rep(i,n-1,0)inv[i]=inv[i+1]*(i+1)%mod;
    	}
    	int qpow(int x,int y) {
    		int ans=1;
    		for(; y; y>>=1,x=x*x%mod)if(y&1)ans=ans*x%mod;
    		return ans;
    	} int C(int n,int m) {
    		if(n<0||m<0||n<m)return 0;
    		return fac[n]*inv[m]%mod*inv[n-m]%mod;
    	}
    	int gcd(int x,int y) {
    		return!y?x:gcd(y,x%y);
    	} int lcm(int x,int y) {
    		return x*y/gcd(x,y);
    	}
    } math;
    // clang-format on
    
    const int maxn = 1e6 + 61;
    char s[maxn], t[maxn];
    
    int q, n, m;
    int rt[maxn];
    struct SegMentTree {
      int ls[maxn << 5], rs[maxn << 5], cnt;
    
      SegMentTree() { cnt = 0; }
    
      void upd(int& p, int l, int r, int x) {
        if (!p) p = ++cnt;
        if (l == r) return;
        int mid = l + r >> 1;
        if (x <= mid)
          upd(ls[p], l, mid, x);
        else
          upd(rs[p], mid + 1, r, x);
      }
    
      int merge(int x, int y) {
        if (!x || !y) return x | y;
        int p = ++cnt;
        ls[p] = merge(ls[x], ls[y]);
        rs[p] = merge(rs[x], rs[y]);
        return p;
      }
    
      int qry(int p, int a, int b, int l, int r) {
        if (!p) return 0;
        if (a <= l && r <= b) return 1;
        int mid = l + r >> 1;
        if (a <= mid && qry(ls[p], a, b, l, mid)) return 1;
        if (b > mid && qry(rs[p], a, b, mid + 1, r)) return 1;
        return 0;
      }
    } smt;
    
    struct Suffix_Auto_Maton {
      int las, cnt;
      int ch[maxn][26], fa[maxn], len[maxn], pos[maxn];
    
      Suffix_Auto_Maton() { las = cnt = 1; }
    
      void clear() {
        rep(i, 1, cnt) {
          fa[i] = len[i] = pos[i] = 0;
          memset(ch[i], 0, sizeof(ch[i]));
        }
        las = cnt = 1;
      }
    
      void ins(int c, int id) {
        int p = las, np = las = ++cnt;
        len[np] = len[p] + 1, pos[np] = id;
        for (; p && !ch[p][c]; p = fa[p]) ch[p][c] = np;
        if (!p) {
          fa[np] = 1;
        } else {
          int q = ch[p][c];
          if (len[q] == len[p] + 1) {
            fa[np] = q;
          } else {
            int nq = ++cnt;
            pos[nq] = pos[q];
            memcpy(ch[nq], ch[q], sizeof(ch[q]));
            len[nq] = len[p] + 1, fa[nq] = fa[q], fa[q] = fa[np] = nq;
            for (; p && ch[p][c] == q; p = fa[p]) ch[p][c] = nq;
          }
        }
      }
    } sam, sam2;
    
    vector<int> g[maxn];
    
    void dfs(int u) {
      for (int v : g[u]) {
        dfs(v);
        rt[u] = smt.merge(rt[u], rt[v]);
      }
    }
    
    int match[maxn];
    void getmatch(int l, int r) {
      int now = 1, nowl = 0;
      rep(i, 1, m) {
        while (233) {
          if (sam.ch[now][s[i] - 'a'] && smt.qry(rt[sam.ch[now][s[i] - 'a']], l + nowl, r, 1, n)) {
            now = sam.ch[now][s[i] - 'a'], nowl++;
            break;
          }
          if (!nowl) break;
          if (--nowl == sam.len[sam.fa[now]]) now = sam.fa[now];
        }
        match[i] = nowl;
      }
    }
    
    signed main() {
      // code begin.
      scanf("%s", s + 1), n = strlen(s + 1), sam.clear();
      rep(i, 1, n) 
    		sam.ins(s[i] - 'a', i), smt.upd(rt[sam.las], 1, n, i);
      rep(i, 2, sam.cnt) 
    		g[sam.fa[i]].pb(i);
      dfs(1);
      int _;
      scanf("%lld", &_);
      while (_--) {
        scanf("%s", s + 1);
        m = strlen(s + 1);
        int l, r;
        scanf("%lld%lld", &l, &r);
        sam2.clear();
        rep(i, 1, m) 
    			sam2.ins(s[i] - 'a', i);
        getmatch(l, r);
        int ans = 0;
        rep(i, 2, sam2.cnt) 
    			ans += max(0ll, sam2.len[i] - max(match[sam2.pos[i]], sam2.len[sam2.fa[i]]));
        printf("%lld
    ", ans);
      }
      return 0;
      // code end.
    }
    
  • 相关阅读:
    《微服务架构设计》——Eventuate Tram框架订阅/消费模式源码解析
    Spring Cloud LoadBalancer原理讲解及自定义负载均衡器
    聊一下 TS 中的交叉类型
    如何理解 TS 类型编程中的 extends 和 infer
    TS 中 never 类型的妙用
    28岁大龄青年相亲记——2021年总结与思考
    Kafka从入门到放弃(三)—— 详说消费者
    Kafka从入门到放弃(二) —— 详说生产者
    Kafka从入门到放弃(一) —— 初识Kafka
    短时间复习通过2021上半年软考软件设计师(附资料)
  • 原文地址:https://www.cnblogs.com/Isaunoya/p/12568819.html
Copyright © 2011-2022 走看看