zoukankan      html  css  js  c++  java
  • CF235C Cyclical Quest

    题意

    显然先把(S)塞进(SAM)中,之后处理每个询问。

    对于一个询问,我们自然不能枚举所有的循环串,于是我们考虑在匹配的过程中删去首字符,加入尾字符。

    先匹配好,求一波答案。之后开始删一个首字符,加一个尾字符,之后再统计,直到所有串统计完。

    维护当前在哪个节点(now)和匹配的长度(len)

    删一个首字符:
    (len--)
    假如(len=len_{fa_{now}}),就向上跳,使(now=fa_{now})

    添一个尾字符:
    一直跳,直到(now)有这个字符的出边,中途跳一次令(len=len_{now})

    code:

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=1e6+10;
    int n,Q,cnt,tim;
    int head[maxn<<1];
    char s[maxn];
    struct edge{int to,nxt;}e[maxn<<2];
    struct SAM
    {
    	int last,tot;
    	int fa[maxn<<1],len[maxn<<1],cnt[maxn<<1],vis[maxn<<1];
    	int ch[maxn<<1][30];
    	inline void init(){last=tot=1;}
    	inline void add(int c)
    	{
    		int now=++tot;cnt[now]=1;len[now]=len[last]+1;
    		int p=last;last=now;
    		while(p&&!ch[p][c])ch[p][c]=now,p=fa[p];
    		if(!p){fa[now]=1;return;}
    		int q=ch[p][c];
    		if(len[q]==len[p]+1)fa[now]=q;
    		else
    		{
    			int nowq=++tot;len[nowq]=len[p]+1;
    			memcpy(ch[nowq],ch[q],sizeof(ch[q]));
    			fa[nowq]=fa[q];fa[q]=fa[now]=nowq;
    			while(p&&ch[p][c]==q)ch[p][c]=nowq,p=fa[p];
    		}
    	}
    }sam;
    inline void add(int u,int v)
    {
    	e[++cnt].nxt=head[u];
    	head[u]=cnt;
    	e[cnt].to=v;
    }
    void dfs(int x)
    {
    	for(int i=head[x];i;i=e[i].nxt)
    		dfs(e[i].to),sam.cnt[x]+=sam.cnt[e[i].to];
    }
    inline int solve(char* s)
    {
    	tim++;
    	int len=strlen(s+1),ans=0,now=1,nowlen=0;
    	for(int i=1;i<=len;i++) 
    	{
    		int c=s[i]-'a';
    		while(now>1&&!sam.ch[now][c])now=sam.fa[now],nowlen=sam.len[now];
    		if(sam.ch[now][c])now=sam.ch[now][c],nowlen++;
    	}
    	if(nowlen==len&&sam.vis[now]!=tim)sam.vis[now]=tim,ans+=sam.cnt[now];
    	for(int i=1;i<len;i++)
    	{
    		int c=s[i]-'a';
    		while(now>1&&!sam.ch[now][c])now=sam.fa[now],nowlen=sam.len[now];
    		if(sam.ch[now][c])now=sam.ch[now][c],nowlen++;
    		if(nowlen>len&&(--nowlen)==sam.len[sam.fa[now]])now=sam.fa[now];
    		if(nowlen==len&&sam.vis[now]!=tim)sam.vis[now]=tim,ans+=sam.cnt[now];
    	}
    	return ans;
    }
    int main()
    {
    	//freopen("test.in","r",stdin);
    	//freopen("test.out","w",stdout);
    	scanf("%s",s+1);n=strlen(s+1);
    	sam.init();
    	for(int i=1;i<=n;i++)sam.add(s[i]-'a');
    	for(int i=2;i<=sam.tot;i++)add(sam.fa[i],i);
    	dfs(1);
    	scanf("%d",&Q);
    	while(Q--)
    	{
    		scanf("%s",s+1);
    		printf("%d
    ",solve(s));
    	}
    	return 0;
    } 
    
  • 相关阅读:
    忙碌的一月
    SharePoint Portal Server 2003书籍计划最新进展
    如何判断Assembly是Debug还是Release?
    C#和C++的一个有意思的差别
    Enterprise Development Reference Architecture(ShadowFax)
    一个“轻量级”的SharePoint文档流转WebPart
    11月25日下午14:00,CSDN在线SharePoint TechTalk
    到北京后的第一篇随笔
    SOA & Messaging Patterns
    操作SharePoint Object Model完成两项操作的文档
  • 原文地址:https://www.cnblogs.com/nofind/p/12074848.html
Copyright © 2011-2022 走看看