zoukankan      html  css  js  c++  java
  • BZOJ5137 [Usaco2017 Dec]Standing Out from the Herd

    Standing Out from the Herd

    定义一个字符串的「独特值」为只属于该字符串的本质不同的非空子串的个数。如 "amy" 与 “tommy” 两个串,只属于 "amy" 的本质不同的子串为 "a" "am" "amy" 共 3 个。只属于 "tommy" 的本质不同的子串为 "t" "to" "tom" "tomm" "tommy" "o" "om" "omm" "ommy" "mm" "mmy" 共 11 个。 所以 "amy" 的「独特值」为 3 ,"tommy" 的「独特值」为 11 。给定 N 个字符集为小写英文字母的字符串,所有字符串的长度和小于 105 ,求出每个字符串「独特值」

    题解

    参照bestfySovietPower的题解。

    广义sam,right集合定义为多个串中出现的位置的并。

    某个子串只出现在一个串中等价于当前状态的right集合只属于一个串。令f[u]表示u状态的right集合属于哪个串,若属于多个串记为-1,建出树以后自下而上合并right即可。

    对每个串插入时新建的cur标记其属于哪个串。然后在parent树上DFS,合并子节点状态就行了。每个点的贡献就是len[i]−len[fa[i]]。

    复杂度O(n)。


    对于这题而言,写正规的SAM比较麻烦,可以直接使用错误做法——每次插入一个串的时候把last赋为1。

    这样做在这道题里面是对的,考虑到如果本来有等价转移,那么就应该把它的状态标记成-1。而错误做法实际上是新建了一个废节点(没有节点能通过ch转移到它),但是这个废节点有fa连向q,所以在以后更新的时候q的状态最终是会被标记成-1的。

    今后做题的时候应该想一下能不能用这种废节点机制简化代码。

    co int N=2e5;
    int last=1,tot=1;
    int ch[N][26],fa[N],len[N],bl[N];
    void extend(int c,int id){
    	int p=last,cur=last=++tot;
    	len[cur]=len[p]+1;
    	for(;p&&!ch[p][c];p=fa[p]) ch[p][c]=cur;
    	if(!p) fa[cur]=1;
    	else{
    		int q=ch[p][c];
    		if(len[q]==len[p]+1) fa[cur]=q;
    		else{
    			int clone=++tot;
    			memcpy(ch[clone],ch[q],sizeof ch[q]);
    			fa[clone]=fa[q],len[clone]=len[p]+1;
    			fa[cur]=fa[q]=clone;
    			for(;ch[p][c]==q;p=fa[p]) ch[p][c]=clone;
    		}
    	}
    	if(bl[cur]&&bl[cur]!=id) bl[cur]=-1;
    	else bl[cur]=id;
    }
    vector<int> e[N];
    int ans[N];
    void dfs(int u){
    	for(int i=0;i<e[u].size();++i) dfs(e[u][i]);
    	if(bl[u]&&bl[u]!=-1) ans[bl[u]]+=len[u]-len[fa[u]];
    	if(bl[fa[u]]&&bl[fa[u]]!=bl[u]) bl[fa[u]]=-1;
    	else bl[fa[u]]=bl[u];
    }
    char str[N];
    int main(){
    	int n=read<int>();
    	for(int i=1;i<=n;++i){
    		scanf("%s",str+1);int l=strlen(str+1);
    		last=1;
    		for(int j=1;j<=l;++j) extend(str[j]-'a',i);
    	}
    	for(int i=2;i<=tot;++i) e[fa[i]].push_back(i);
    	dfs(1);
    	for(int i=1;i<=n;++i) printf("%d
    ",ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    WPF:DataGrid 自动生成行号
    C#:WinForm之Command
    i.MX RT1010之FlexIO模拟SSI外设
    i.MX RT1010之FlexIO模拟I2S外设
    i.MX RT600之DSP开发环境调试篇
    i.MX RT600之DSP调试环境搭建篇
    i.MX RT600之DMIC外设介绍及应用
    i.MX RT600之I2S外设介绍及应用
    ssm框架思维-登录
    idea里面搭建SSM框架-crud
  • 原文地址:https://www.cnblogs.com/autoint/p/10906009.html
Copyright © 2011-2022 走看看