zoukankan      html  css  js  c++  java
  • 【luogu P6139】【模板】广义后缀自动机(广义 SAM)

    【模板】广义后缀自动机(广义 SAM)

    题目链接:luogu P6139

    题目大意

    给你 n 个串,问你这里一共有多少个本质不同的子串。

    思路

    其实这道题我们只需要每次插入一个串之后插下一个串之间回到起点就可以了。

    所以 SAM 还是普通的 SAM,求个数也是直接 (len_i-len_{fa_i}),没有什么太多少说的。

    代码

    #include<cstdio>
    #include<cstring>
    #define ll long long
    
    using namespace std;
    
    struct SAM {
    	int len, fa;
    	ll size;
    	int son[26];
    }t[2000002];
    int n, sn, tot, lst;
    char s[1000001];
    ll ans;
    
    void SAM_insert(int now) {
    	int p = lst;
    	int np = ++tot;
    	lst = np;
    	t[np].size = 1;
    	t[np].len = t[p].len + 1;
    	for (; p && !t[p].son[now]; p = t[p].fa)
    		t[p].son[now] = np;
    	
    	if (!p) t[np].fa = 1;
    		else {
    			int q = t[p].son[now];
    			if (t[q].len == t[p].len + 1) t[np].fa = q;
    				else {
    					int nq = ++tot;
    					t[nq] = t[q];
    					t[nq].size = 0;
    					t[nq].len = t[p].len + 1;
    					t[q].fa = t[np].fa = nq;
    					for (; p && t[p].son[now] == q; p = t[p].fa)
    						t[p].son[now] = nq;
    				}
    		}
    }
    
    int main() {
    	scanf("%d", &n);
    	
    	tot = 1;
    	for (int i = 1; i <= n; i++) {
    		scanf("%s", s + 1);
    		sn = strlen(s + 1);
    		
    		lst = 1;//每次重新回起点搞
    		for (int j = 1; j <= sn; j++)
    			SAM_insert(s[j] - 'a');
    	}
    	
    	for (int i = 1; i <= tot; i++)
    		ans += t[i].len - t[t[i].fa].len;
    	printf("%lld", ans);
    	
    	return 0;
    }
    
  • 相关阅读:
    Delphi 获取时间的年月日
    Tlist删除技巧
    SQL Server 2008 允许远程连接的配置
    initialization & finalization
    display属性(元素转换)
    float 浮动
    盒模型
    行内元素和块级元素水平及垂直居中
    html常用的几个标签
    html基础
  • 原文地址:https://www.cnblogs.com/Sakura-TJH/p/luogu_P6139.html
Copyright © 2011-2022 走看看