• P4081 [USACO17DEC]Standing Out from the Herd P [广义SAM]


    我们直接把重复的部分去掉。

    (sum len_i - len_{fa_i})

    #include <bits/stdc++.h>
    using namespace std;
    
    const int maxn = 2e5 + 62;
    char s[maxn], str[maxn];
    int tot = 0 ;
    long long Ans[maxn] ;
    
    struct SAM {
    	int ch[maxn][26], cnt, len[maxn], fa[maxn];
    
    	SAM() {
    		cnt = 1;
    	}
    
    	int ins(int c, int las) {
    		int p = las, np = ++cnt;
    		len[np] = len[p] + 1;
    		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;
    				memcpy(ch[nq], ch[q], sizeof(ch[q]));
    				fa[nq] = fa[q], fa[q] = fa[np] = nq, len[nq] = len[p] + 1;
    				for (; p && ch[p][c] == q; p = fa[p]) ch[p][c] = nq;
    			}
    		}
    		return np;
    	}
    	
    	int id[maxn] ;
    	
    	void col(int x , int c) {
    		for( ; x && id[x] ^ c && ~ id[x] ; x = fa[x])
    			id[x] = (id[x]) ? -1 : c ;
    	}
    	
    	void calc() {
    		int c = 1 , p = 1 ;
    		for(int i = 1 ; i <= tot ; i ++) {
    			if(! isspace(str[i])) {
    				col(p = ch[p][str[i] - 'a'] , c) ;
    			}
    			else {
    				p = 1 , ++ c ;
    			}
    		}
    		for(int i = 1 ; i <= cnt ; i ++) {
    			if(~ id[i]) {
    				Ans[id[i]] += len[i] - len[fa[i]] ;
    			}
    		}
    	}
    } sam;
    
    struct Trie {
    	int ch[maxn][26], cnt, qwq[maxn], fa[maxn];
    
    	Trie() {
    		cnt = 1;
    	}
    
    	void ins(int len) {
    		int p = 1;
    		for (int i = 1; i <= len; i++) {
    			int c = s[i] - 'a';
    			if (!ch[p][c]) ch[p][c] = ++cnt, qwq[cnt] = c, fa[cnt] = p;
    			p = ch[p][c];
    		}
    	}
    
    	int pos[maxn];
    
    	void buildsam() {
    		queue<int> q;
    		for (int i = 0; i < 26; i++)
    			if (ch[1][i]) q.push(ch[1][i]);
    		pos[1] = 1;
    		while (!q.empty()) {
    			int u = q.front();
    			q.pop();
    			pos[u] = sam.ins(qwq[u], pos[fa[u]]);
    			for (int i = 0; i < 26; i++)
    				if (ch[u][i]) q.push(ch[u][i]);
    		}
    	}
    } trie;
    
    void cpy(int len) {
    	for(int i = 1 ; i <= len ; i ++) str[++ tot] = s[i] ;
    	str[++ tot] = '
    ' ;
    }
    
    int main() {
    	int _;
    	scanf("%d", &_);
    	for(int i = 1 ; i <= _ ; i ++) scanf("%s", s + 1), trie.ins(strlen(s + 1)), cpy(strlen(s + 1));
    	trie.buildsam(), sam.calc();
    	for(int i = 1 ; i <= _ ; i ++) printf("%lld
    " , Ans[i]) ;
    	return 0;
    }
    
  • 相关阅读:
    高数基础知识整理12.微分方程
    x(1-x)及其更高次在区间[0,1]上的积分值
    PHP中的http协议
    php简单实现MVC
    如何用jQuery获得select的值
    面向对象思想介绍
    MySQL 日期和时间戳的转换 | 以及DATE_FORMAT()用法
    js将时间转换为时间戳
    PHP中sql语句如何使用变量
    四种简单的sql语句(增删改查语句)
  • 原文地址:https://www.cnblogs.com/Isaunoya/p/12568935.html
Copyright © 2020-2023  润新知