• P4081 [USACO17DEC]Standing Out from the Herd P 广义SAM


    题意:

    戳这里

    分析:

    一看见本质不同的字符串 ( o) (SAM)

    再一看,字符串集合 ( o) 广义 (SAM)

    所以这个题的做法就是,建一颗广义 (SAM) , (dfs) 这个 (SAM) ,把只出现了一次的点标起来,它的贡献就是 (len[x]-len[link[x]]) ,注意没有被标过的点,他属于它的儿子所在的集合

    tip:

    广义SAM好像不能像普通的SAM一样,通过基数排序得到它的拓扑序

    代码:

    #include<bits/stdc++.h>
    #define pii pair<int,int>
    #define mk(x,y) make_pair(x,y)
    #define lc rt<<1
    #define rc rt<<1|1
    #define pb push_back
    #define fir first
    #define sec second
    
    using namespace std;
    
    namespace zzc
    {
    	inline int read()
    	{
    		int x=0,f=1;char ch=getchar();
    		while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
    		while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
    		return x*f;
    	}
    	
    	const int maxn = 2e5+5;
    	int n;
    	long long ans[maxn];
    	char ch[maxn];
    	vector<int> tmp[maxn];
    	
    	namespace suffix_automaton//¹ãÒåSAMÔÚÏß¹¹Ôì°æ 
    	{
    		int cnt,lst;
    		int link[maxn],len[maxn],trans[maxn][26],flag[maxn];
    		
    		void insert(int x,int p)
    		{
    			if(trans[lst][x])
    			{
    				int tmp=lst,q=trans[tmp][x];
    				if(len[tmp]+1==len[q])
    				{
    					flag[q]=-1;
    					lst=q;
    				}
    				else
    				{
    					int clone=++cnt;
    					len[clone]=len[tmp]+1;
    					link[clone]=link[q];
    					link[q]=clone;
    					for(int i=0;i<26;i++) trans[clone][i]=trans[q][i];
    					for(;tmp&&trans[tmp][x]==q;tmp=link[tmp]) trans[tmp][x]=clone; 
    					lst=clone;flag[clone]=p;
    				}
    				return ;
    			}
    			int cur=++cnt,tmp=lst;lst=cnt;
    			len[cur]=len[tmp]+1;
    			if(!flag[cur]) flag[cur]=p;
    			else flag[cur]=-1;
    			for(;tmp&&!trans[tmp][x];tmp=link[tmp]) trans[tmp][x]=cur;
    			if(!tmp)
    			{
    				link[cur]=1;
    			}
    			else
    			{
    				int q=trans[tmp][x];
    				if(len[tmp]+1==len[q])
    				{
    					link[cur]=q;
    				}
    				else
    				{
    					int clone=++cnt;
    					len[clone]=len[tmp]+1;
    					link[clone]=link[q];
    					link[cur]=link[q]=clone;
    					for(int i=0;i<26;i++) trans[clone][i]=trans[q][i];
    					for(;tmp&&trans[tmp][x]==q;tmp=link[tmp]) trans[tmp][x]=clone; 
    				}
    			}
    		}
    	}
    	using namespace suffix_automaton;
    	
    	void dfs(int u)
    	{
    		for(auto v:tmp[u])
    		{
    			dfs(v);
    			if(!flag[u]) flag[u]=flag[v];
    			else if(flag[u]!=flag[v]) flag[u]=-1;
    		}
    		if(flag[u]!=-1) ans[flag[u]]+=len[u]-len[link[u]];
    	}
    	
    	void work()
    	{
    		n=read();cnt=1;
    		for(int i=1;i<=n;i++)
    		{
    			scanf("%s",ch+1);
    			int len=strlen(ch+1);
    			lst=1;
    			for(int j=1;j<=len;j++) insert(ch[j]-'a',i);
    		}
    		for(int i=1;i<=cnt;i++) tmp[link[i]].push_back(i);
    		dfs(1);
    		for(int i=1;i<=n;i++) printf("%lld
    ",ans[i]);
    	}
    
    }
    
    int main()
    {
    	zzc::work();
    	return 0;
    }
    
    
  • 相关阅读:
    Nokia Lumia 800销售反馈 苹果iPhone、三星Galaxy不敌800设计
    各大网站用户数据库被爆,遭大量网友下载
    最美发明家:GPS、手机通讯网都源自她的发明
    iPhone5或明年下半年发布 配备iOS6和A6芯片
    保存文件到手机内存
    2012年十大科技趋势:NFC、语音控制与弯曲屏
    电脑报独家报道:宽带升级全国真相调查
    Android的电话拨号器
    Java程序员成长之路(接口与抽象类究竟有什么区别)
    联系人相关
  • 原文地址:https://www.cnblogs.com/youth518/p/14198454.html
Copyright © 2020-2023  润新知