zoukankan      html  css  js  c++  java
  • 【[USACO17DEC]Standing Out from the Herd】

    题目

    不会广义(SAM)

    但信仰插入特殊字符就可以搞定一切了

    我们先把所有的串搞在一起建出一个(SAM),记得在中间插入特殊字符

    对于(parent)树上的一个节点,只有当其(endpos)集合中的所有元素都来自于同一个串的时候我们才对它进行统计

    所以我们需要维护一个(parent)树上子树最大值和最小值,这样我们就能很快的判断这个(endpos)是否合法了

    但是非常棘手的一类情况是我们插进去的特殊字符,显然(SAM)里有一些奇奇怪怪的子串中含有特殊字符

    那也好办,我们存好每个串的起始位置只要那些没有跨越特殊字符的就好了

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #define maxn 200005
    #define re register
    #define max(a,b) ((a)>(b)?(a):(b))
    #define min(a,b) ((a)<(b)?(a):(b))
    struct E{int v,nxt;} e[maxn];
    char S[maxn];
    int m,n,lst=1,cnt=1,num;
    int len[maxn],fa[maxn],son[maxn][27],mx[maxn],ml[maxn];
    int f[maxn],head[maxn],d[maxn],Ans[maxn],li[maxn];
    inline void add(int x,int y) {e[++num].v=y;e[num].nxt=head[x];head[x]=num;}
    void dfs(int x) {
    	for(re int i=head[x];i;i=e[i].nxt) 
    		dfs(e[i].v),mx[x]=max(mx[e[i].v],mx[x]),ml[x]=min(ml[e[i].v],ml[x]),d[x]|=d[e[i].v];
    }
    inline void ins(int c,int o)
    {
    	int f=lst,p=++cnt; lst=p;
    	len[p]=len[f]+1,mx[p]=ml[p]=o;
    	if(c==26) d[p]=1;
    	while(f&&!son[f][c]) son[f][c]=p,f=fa[f];
    	if(!f) {fa[p]=1;return;}
    	int x=son[f][c];
    	if(len[f]+1==len[x]) {fa[p]=x;return;}
    	int y=++cnt;
    	len[y]=len[f]+1,fa[y]=fa[x],fa[x]=fa[p]=y;
    	for(re int i=0;i<27;i++) son[y][i]=son[x][i];
    	while(f&&son[f][c]==x) son[f][c]=y,f=fa[f];
    }
    int main()
    {
    	memset(ml,20,sizeof(ml));
    	scanf("%d",&m);
    	for(re int i=1;i<=m;i++)
    	{
    		scanf("%s",S+1);
    		int len=strlen(S+1);li[i]=n+1;
    		for(re int j=1;j<=len;j++) ins(S[j]-'a',++n),f[n]=i;
    		ins(26,++n);
    	}
    	for(re int i=2;i<=cnt;i++) add(fa[i],i);
    	dfs(1);
    	for(re int i=2;i<=cnt;i++)
    	{
    		if(d[i]) continue;
    		if(f[mx[i]]!=f[ml[i]]) continue;
    		int minlen=len[fa[i]]+1;
    		if(f[mx[i]-minlen+1]!=f[mx[i]]) continue;
    		if(f[mx[i]-len[i]+1]==f[mx[i]]) Ans[f[mx[i]]]+=len[i]-len[fa[i]];
    			else Ans[f[mx[i]]]+=mx[i]-li[f[mx[i]]]-minlen+2;
    	}
    	for(re int i=1;i<=m;i++) printf("%d
    ",Ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    迷宫 广搜
    steam 字符串hash or map
    Karen与测试 奇迹淫巧+快速幂
    puzzle 期望树形DP
    函数 贪心
    P1032 字串变换 字符串
    等效集合 图论(缩点)
    高斯消元
    loj2537. 「PKUWC2018」Minimax
    loj2538. 「PKUWC2018」Slay the Spire
  • 原文地址:https://www.cnblogs.com/asuldb/p/10249310.html
Copyright © 2011-2022 走看看