• SPOJ 8222 NSUBSTR(SAM)


    这几天看了N多论文研究了下后缀自己主动机。刚開始蛋疼的看着极短的代码和clj的论文硬是看不懂,后来结合其它几篇论文研究了下。总算是明确了一些

    推荐文章http://blog.sina.com.cn/s/blog_70811e1a01014dkz.html

    看了几篇文章认为还是这篇写的清晰明了,建议看几遍明确怎样建SAM再看了clj的论文。

    clj的论文中对性质的研究比較深入

    以下是clj论文里推荐的一题,题意:给一个字符串S,令F(x)表示S的全部长度为x的子串中,出现次数的最大值。求F(1)..F(Length(S)) (感谢clj的翻译>_<)

    首先按顺序建SAM。一个串的|Right|就是出现次数。

    因为父节点的Right集合正好等于子节点Right集合的并集,于是能够拓扑排序从后往前找,然后每次再把子节点的Right加到pre节点上就可以。这里拓扑排序使用了类似于计数排序的思想。见代码

    #include<iostream>//SAM
    #include<cstring>
    #include<cmath>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int N=250005<<1;
    int last,tot,son[N][26],pre[N],step[N],cnt[N],Q[N],g[N],f[N];
    char s[N];
    void ins(int x,int m){
    	int p=last,np=++tot;
    	step[np]=m,last=np,g[np]++;
    	for(;!son[p][x] && p!=-1;p=pre[p])	son[p][x]=np;
    	if(p==-1)	return;
    	else{
    		int q=son[p][x];
    		if(step[q]==step[p]+1)	pre[np]=q;
    		else{
    			step[++tot]=step[p]+1;
    			int nq=tot;
    			memcpy(son[nq],son[q],sizeof(son[q]));
    			pre[nq]=pre[q];
    			pre[q]=pre[np]=nq;
    			for(;son[p][x]==q && p!=-1;p=pre[p])	son[p][x]=nq;	
    		}
    	}
    }
    int main(){
    	pre[0]=-1;
    	scanf("%s",s);
    	int l=strlen(s);
    	for(int i=0;i<l;++i)	ins(s[i]-'a',i+1);
    	for(int i=1;i<=tot;++i)	cnt[step[i]]++;
    	for(int i=1;i<=tot;++i)	cnt[i]+=cnt[i-1];
    	for(int i=1;i<=tot;++i)	Q[cnt[step[i]]--]=i;
    	for(int i=tot;i>=1;--i)	printf("%d
    ",step[Q[i]]);
    	for(int i=tot;i>=1;--i)	f[step[Q[i]]]=max(f[step[Q[i]]],g[Q[i]]),g[pre[Q[i]]]+=g[Q[i]];
    	for(int i=1;i<=l;++i)	printf("%d
    ",f[i]);
    	return 0;
    }
    

  • 相关阅读:
    性能相差7千倍的ToString方法
    重构打造爱因斯坦谜题最快算法
    Windows Phone 7将胜出的五条论据
    让火狐狸遨游起来
    What's your understanding about RIA?
    [English Practise]Action when meeting a problem at work
    linux socket编程
    nginx服务器的配置
    要搬到csdn了
    搭建一个全栈式的HTML5移动应用框架
  • 原文地址:https://www.cnblogs.com/cxchanpin/p/6758245.html
Copyright © 2020-2023  润新知