zoukankan      html  css  js  c++  java
  • HDU3518 Boring Counting(后缀自动机)

    给出一个字符串

    询问有多少个子串满足

    出现至少两次,且不重叠。

    做法:

    建出SAM。

    对每个节点维护最大的endpos位置L和最小的endpos位置R

    然后对每个节点\(i\),取\(min(R-L,len[i])-len[link[i]]\)就是对答案的贡献。

    求和即可。

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=1e5+10;
    int nxt[maxn][26],link[maxn],len[maxn],lst=1,tot=1;
    int L[maxn],R[maxn];
    char s[maxn];
    vector<int> g[maxn];
    void init () {
    	for (int i=0;i<=tot;i++) {
    		for (int j=0;j<26;j++) {
    			nxt[i][j]=0;
    		}
    		link[i]=len[i]=0;
    		L[i]=1000000000;
    		R[i]=0;
    		g[i].clear();
    	}
    	lst=tot=1;
    }
    void sam_extend (char c) {
    	int cur=++tot;
    	len[cur]=len[lst]+1;
    	int p=lst;
    	while (p&&!nxt[p][c-'a']) {
    		nxt[p][c-'a']=cur;
    		p=link[p];
    	}
    	if (!p) link[cur]=1;
    	else {
    		int q=nxt[p][c-'a'];
    		if (len[p]+1==len[q]) {
    			link[cur]=q;
    		}
    		else {
    			int clone=++tot;
    			len[clone]=len[p]+1;
    			for (int i=0;i<26;i++) nxt[clone][i]=nxt[q][i];
    			link[clone]=link[q];
    			while (p&&nxt[p][c-'a']==q) {
    				nxt[p][c-'a']=clone;
    				p=link[p];
    			}
    			link[q]=link[cur]=clone;
    		}
    	}
    	lst=cur;
    }
    void dfs (int u) {
    	for (int v:g[u]) {
    		dfs(v);
    		L[u]=min(L[u],L[v]);
    		R[u]=max(R[u],R[v]);
    	}
    }
    int main () {
    	for (int i=0;i<maxn;i++) L[i]=1000000000;
    	while (1) {
    		scanf("%s",s);
    		if (strlen(s)==1&&s[0]=='#') break;
    		for (int i=0;i<strlen(s);i++) {
    			sam_extend(s[i]);
    			L[lst]=R[lst]=i;
    		}
    		for (int i=2;i<=tot;i++) g[link[i]].push_back(i);
    		dfs(1);
    		long long ans=0;
    		for (int i=2;i<=tot;i++) {
    			//printf("%d %d %d %d\n",L[i],R[i],len[i],len[link[i]]);
    			ans+=max(0,min(R[i]-L[i],len[i])-len[link[i]]);
    		}
    		printf("%lld\n",ans);
    		init();
    	}
    }
    
  • 相关阅读:
    linux 11201(11203) ASM RAC 安装
    [学习笔记]多项式对数函数
    linux 10201 ASM RAC 安装+升级到10205
    tar
    [学习笔记]多项式开根
    gzip
    小朋友和二叉树
    zip
    bzoj5016 一个简单的询问
    unzip
  • 原文地址:https://www.cnblogs.com/zhanglichen/p/15541710.html
Copyright © 2011-2022 走看看