zoukankan      html  css  js  c++  java
  • SAM 做题记录

    pigeon->gugugu();

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

    建出 SAM 后 在 parent tree 上 dp,对每个节点算它子树里面叶子节点个数,然后根据题意统计答案即可。

    Code
    #include<bits/stdc++.h>
    using namespace std;
    const int N=1000005*3;
    struct node{int len,link,to[30];};
    int n,hd[N],tot,sz[N];
    long long ans;
    char s[N];
    struct edge{int t,nxt;}es[N<<1];
    void add(int u,int v){es[++tot]=(edge){v,hd[u]};hd[u]=tot;}
    namespace SAM{
    	node state[N];
    	int rt=1,last=1,tot=1;
    	void extend(int ch){
    		int cur=++tot,p,q; 
    		sz[cur]=1;
    		state[cur].len=state[last].len+1;
    		for(p=last;p&&!state[p].to[ch];p=state[p].link)state[p].to[ch]=cur;
    		if(!p)state[cur].link=rt;
    		else{
    			q=state[p].to[ch];
    			if(state[p].len+1==state[q].len)state[cur].link=q;
    			else{
    				int clone=++tot;
    				state[clone]=state[q];
    				state[clone].len=state[p].len+1;
    				state[cur].link=state[q].link=clone;
    				for(;p&&state[p].to[ch]==q;p=state[p].link)state[p].to[ch]=clone;
    			}
    		}
    		last=cur;
    	}
    }
    void dfs(int u){
    	for(int i=hd[u];i;i=es[i].nxt)dfs(es[i].t),sz[u]+=sz[es[i].t];
    	if(sz[u]!=1)ans=max(ans,1LL*sz[u]*SAM::state[u].len);
    } 
    int main(){
    	scanf("%s",s);n=strlen(s);
    	for(int i=0;i<n;i++)SAM::extend(s[i]-'a');
    	for(int i=2;i<=SAM::tot;i++)add(SAM::state[i].link,i);
    	dfs(SAM::rt);
    	printf("%lld
    ",ans);
    	return 0;
    }
    

    P1368 【模板】最小表示法

    两倍长建 SAM,每次走最小的边,走 (n) 次即可。

    Code
    #include<bits/stdc++.h>
    using namespace std;
    const int N=300005*3;
    struct node{int len,link;map<int,int>to;};
    struct Suffix_Automation{
    	node state[N];
    	int rt=1,last=1,tot=1;
    	void extend(int ch){
    		int cur=++tot,p,q;
    		state[cur].len=state[last].len+1;
    		for(p=last;p&&!state[p].to[ch];p=state[p].link)state[p].to[ch]=cur;
    		if(!p)state[cur].link=rt;
    		else{
    			q=state[p].to[ch];
    			if(state[p].len+1==state[q].len)state[cur].link=q;
    			else{
    				int clone=++tot;
    				state[clone]=state[q];
    				state[clone].len=state[p].len+1;
    				state[cur].link=state[q].link=clone;
    				for(;p&&state[p].to[ch]==q;p=state[p].link)state[p].to[ch]=clone;
    			}
    		}
    		last=cur;
    	}
    }SAM;
    int n,a[N];
    map<int,int>::iterator it;
    int main(){
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++)scanf("%d",&a[i]),SAM.extend(a[i]);
    	for(int i=1;i<=n;i++)SAM.extend(a[i]);
    	for(int i=1,nw=SAM.rt;i<=n;i++)it=SAM.state[nw].to.begin(),printf("%d ",it->first),nw=it->second;
    	return 0;
    }
    

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

    这题貌似和第一题很像,其实处理方法不一样。

    根据 (operatorname{link}) 的定义,状态 (v) 对应的字符串个数为 (operatorname{len}(i)-operatorname{len}(operatorname{link}(i))),那么每次加字符的时候更新就可以了。

    Code
    #include<bits/stdc++.h>
    using namespace std;
    const int N=300005*3;
    struct node{int len,link;map<int,int>to;};
    struct Suffix_Automation{
    	node state[N];
    	int rt=1,last=1,tot=1;
    	long long ans;
    	void extend(int ch){
    		int cur=++tot,p,q;
    		state[cur].len=state[last].len+1;
    		for(p=last;p&&!state[p].to[ch];p=state[p].link)state[p].to[ch]=cur;
    		if(!p)state[cur].link=rt;
    		else{
    			q=state[p].to[ch];
    			if(state[p].len+1==state[q].len)state[cur].link=q;
    			else{
    				int clone=++tot;
    				state[clone]=state[q];
    				state[clone].len=state[p].len+1;
    				ans-=state[q].len-state[state[q].link].len;
    				state[cur].link=state[q].link=clone;
    				ans+=state[q].len-state[state[q].link].len;
    				ans+=state[clone].len-state[state[clone].link].len;
    				for(;p&&state[p].to[ch]==q;p=state[p].link)state[p].to[ch]=clone;
    			}
    		}
    		ans+=state[cur].len-state[state[cur].link].len;
    		last=cur;
    	}
    }SAM;
    int n,a[N];
    int main(){
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++)scanf("%d",&a[i]),SAM.extend(a[i]),printf("%lld
    ",SAM.ans);
    	return 0;
    }
    
    
  • 相关阅读:
    系统维护相关问题
    Python环境维护
    哈希表解决字符串问题
    论文笔记二:《A Tutoral on Spectral Clustering》
    论文笔记之哈希学习比较--《Supervised Hashing with Kernels》《Towards Optimal Binary Code Learning via Ordinal Embedding》《Top Rank Supervised Binary Coding for Visual Search》
    Java中String、StringBuffer、StringBuilder的比较与源 代码分析
    浙大pat1040 Longest Symmetric String(25 分)
    浙大pat1039 Course List for Student(25 分)
    浙大pat---1036 Boys vs Girls (25)
    百炼oj-4151:电影节
  • 原文地址:https://www.cnblogs.com/happydef/p/sam-todo.html
Copyright © 2011-2022 走看看