zoukankan      html  css  js  c++  java
  • [bzoj2746][HEOI2012]旅行问题 _AC自动机_倍增

    [HEOI2012]旅行问题

    题目链接https://www.lydsy.com/JudgeOnline/problem.php?id=2746


    题解

    这个是讲课时候的题。

    讲课的时候都在想怎么后缀自动机....

    当然是能做啦,$SAM$这么强。

    实际上是个$AC$自动机,按照题目模拟就行了。

    代码

    #include <bits/stdc++.h>
    
    using namespace std;
    
    typedef long long ll;
    
    const int N = 1 << 20 ;
    
    const int mod = 1000000007 ;
    
    const int P = 21 ;
    
    queue <int> Q;
    
    int n, m, ch[N][26], fail[N][25], dep[N], tail, cnt, pos[N << 1], lenth[N];
    
    char str[N];
    
    ll Hash[N];
    
    void insert() {
    	int len = strlen(str);
    	int p = 0;
    	for (int i = 0; i < len; i ++ ) {
    		int c = str[i] - 'a';
    		if (!ch[p][c]) {
    			ch[p][c] = ++tail;
    			Hash[ch[p][c]] = (((Hash[p] * 26) % mod) + c) % mod;
    		}
    		pos[ ++ cnt] = ch[p][c]; 
    		p = ch[p][c];
    	}   
    }
    
    void getfail() {
    	dep[0] = 0;
    	for (int i = 0; i < 26; i ++ ) {
    		if (ch[0][i]) {
    			fail[ch[0][i]][0] = 0;
    			dep[ch[0][i]] = 1;
    			Q.push(ch[0][i]);
    		}
    	}
    	while (!Q.empty()) {
    		int top = Q.front();
    		Q.pop();
    		for (int i = 0; i < 26; i ++ ) {
    			if (!ch[top][i]) {
    				ch[top][i] = ch[fail[top][0]][i];
    				continue;
    			}
    			int u = ch[top][i];
    			fail[u][0] = ch[fail[top][0]][i];
    			dep[u] = dep[fail[u][0]] + 1;
    			for (int j = 1; j < P; j ++ ) {
    				fail[u][j] = fail[fail[u][j - 1]][j - 1];
    			}
    			Q.push(u);
    		}
    	}   
    }
    
    int getlca(int u, int v) {
    	if (dep[u] < dep[v]) {
    		swap(u, v);
    	}
    	int d = dep[u] - dep[v];
    	for (int i = 0; d; d >>= 1, i ++ ) {
    		if (d & 1) {
    			u = fail[u][i];
    		}
    	}
    	if (u == v) {
    		return u;
    	}
    	for (int p = P - 1; p >= 0; p -- ) {
    		if (fail[u][p] != fail[v][p]) {
    			u = fail[u][p];
    			v = fail[v][p];   
    		}
    	}   
    	return fail[u][0];
    }
    
    int main() {
    	scanf("%d", &n);
    	memset(fail, 0, sizeof fail);
    	lenth[0] = 0;
    	for (int i = 1; i <= n; i ++ ) {
    		scanf("%s", str);
    		insert();
    		lenth[i] = strlen(str);
    		lenth[i] += lenth[i - 1];
    	}
    	getfail();
    	scanf("%d", &m);
    	while (m -- ) {
    		int p1, l1, p2, l2;
    		scanf("%d%d%d%d", &p1, &l1, &p2, &l2);
    		int t1 = pos[lenth[p1 - 1] + l1];
    		int t2 = pos[lenth[p2 - 1] + l2];
    		int lca = getlca(t1, t2);
    		printf("%lld
    ", Hash[lca]);
    	}
    	return 0;
    }
    

    小结:注意一下AC自动机找LCA要倍增,别直接跳fail......

  • 相关阅读:
    Debug权限提升
    QTime的本质上是一个int,QDateTime本质上是一个qint64
    QString先于QObject存在,因为QObject::objectName()返回的是QString
    C++杂记:运行时类型识别(RTTI)与动态类型转换原理
    gcc/g++编译(生动形象,从最容易入手的hello world解释了库的概念)
    分布式存储
    开源代码——Crouton
    android studio
    WebRTC
    FileProvider是个什么东西?
  • 原文地址:https://www.cnblogs.com/ShuraK/p/11421154.html
Copyright © 2011-2022 走看看