zoukankan      html  css  js  c++  java
  • [BZOJ2780][SPOJ8093]Sevenk Love Oimaster

    bzoj
    luogu

    题面

    给定n个模板串,以及m个查询串。
    依次查询每一个查询串是多少个模板串的子串。

    sol

    广义后缀自动机裸题?
    先建出(SAM),然后记录一下每个节点分别在多少个模板串里出现过。
    对于询问直接在(SAM)上跑匹配就行了。

    code

    #include<cstdio>
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    using namespace std;
    const int N = 2e5+5;
    int n,m,last=1,tot=1,tr[N][26],fa[N],len[N],cnt[N],vis[N];
    string s[N],ss;
    void extend(int c)
    {
    	int v=last,u=++tot;last=u;
    	len[u]=len[v]+1;
    	while (v&&!tr[v][c]) tr[v][c]=u,v=fa[v];
    	if (!v) fa[u]=1;
    	else{
    		int x=tr[v][c];
    		if (len[x]==len[v]+1) fa[u]=x;
    		else{
    			int y=++tot;
    			memcpy(tr[y],tr[x],sizeof(tr[y]));
    			fa[y]=fa[x];fa[x]=fa[u]=y;len[y]=len[v]+1;
    			while (v&&tr[v][c]==x) tr[v][c]=y,v=fa[v];
    		}
    	}
    }
    int main()
    {
    	ios::sync_with_stdio(false);
    	cin>>n>>m;
    	for (int i=1,l;i<=n;++i)
    	{
    		cin>>s[i];l=s[i].length();
    		last=1;
    		for (int j=0;j<l;++j) extend(s[i][j]-'a');
    	}
    	for (int i=1;i<=n;++i)
    		for (int j=0,l=s[i].length(),now=1;j<l;++j)
    		{
    			now=tr[now][s[i][j]-'a'];
    			int t=now;
    			while (t&&vis[t]!=i) cnt[t]++,vis[t]=i,t=fa[t];
    		}
    	while (m--)
    	{
    		cin>>ss;int l=ss.length(),now=1;
    		for (int i=0;i<l;++i)
    			now=tr[now][ss[i]-'a'];
    		printf("%d
    ",cnt[now]);
    	}
    	return 0;
    }
    
  • 相关阅读:
    第04组 Beta冲刺 (3/5)
    第04组 Beta冲刺 (2/5)
    第04组 Beta冲刺 (1/5)
    软工实践个人总结
    第09组 每周小结(3/3)
    第09组 每周小结(2/3)
    第09组 每周小结(1/3)
    第09组 Beta冲刺 总结
    第09组 Beta冲刺 (5/5)
    第09组 Beta冲刺 (4/5)
  • 原文地址:https://www.cnblogs.com/zhoushuyu/p/8695358.html
Copyright © 2011-2022 走看看