zoukankan      html  css  js  c++  java
  • CodeForces 235C Cyclical Quest(后缀自动机)

    【题目链接】 http://codeforces.com/contest/235/problem/C

     

    【题目大意】

      给出一个字符串,给出一些子串,问每个子串分别在母串中圆环匹配的次数,圆环匹配的意思是将该子串拆成两段再首位交换相接的串和母串匹配,比如aaab变成baaa,abaa,aaba再进行匹配。

    【题解】

      根据母串建立SAM,一个字符串在母串中匹配的次数就是|Right(x)|,
      我们将子串复制一份,在母串中匹配到的所有长度为大于len的|right|的总和就是答案。

    【代码】

    #include <cstdio>
    #include <cstring>
    #include <algorithm> 
    #include <vector>
    using namespace std;
    const int N=2000005;
    char s[N];
    struct sam{
    	  int p,q,np,nq,cnt,last,a[N][26],l[N],f[N];
    	  sam(){cnt=0;last=++cnt;}
    	  void extend(int c){
    		    p=last;np=last=++cnt;l[np]=l[p]+1;
    		    while(!a[p][c]&&p)a[p][c]=np,p=f[p];
    		    if(!p)f[np]=1;
    		    else{
    			      q=a[p][c];
    			      if(l[p]+1==l[q])f[np]=q;
    			      else{
    				        nq=++cnt;l[nq]=l[p]+1;
    				        memcpy(a[nq],a[q],sizeof(a[q]));
    				        f[nq]=f[q]; f[np]=f[q]=nq;
    				        while(a[p][c]==q)a[p][c]=nq,p=f[p];
    			      }
    		    }
    	  }int b[N],x[N],r[N];
    	  void build(){
    		    scanf("%s",s+1);
    		    int len=strlen(s+1);
    		    for(int i=1;i<=len;i++)extend(s[i]-'a');
    		    for(int i=1;i<=cnt;i++)b[l[i]]++;
    		    for(int i=1;i<=len;i++)b[i]+=b[i-1];
    		    for(int i=1;i<=cnt;i++)x[b[l[i]]--]=i;
    		    for(int i=p=1;i<=len;i++){p=a[p][s[i]-'a'];r[p]++;}
    		    for(int i=cnt;i;i--)r[f[x[i]]]+=r[x[i]];
    	  }vector<int>ans;
    	  bool flag[N];
    	  void solve(){
    	      long long tot=0;
    		    scanf("%s",s+1);
    		    int len=strlen(s+1),p=1,tmp=0;
    		    for(int i=1;i<len;i++)s[i+len]=s[i];
    		    for(int i=1;i<=len*2-1;i++){
    			      int c=s[i]-'a';
    			      if(a[p][c])p=a[p][c],tmp++;
    			      else{
    				        while(p&&!a[p][c])p=f[p];
    				        if(!p)p=1,tmp=0;
    				        else tmp=l[p]+1,p=a[p][c];
    			      }while(l[f[p]]>=len)p=f[p],tmp=l[p];
    			      if(!flag[p]&&tmp>=len)ans.push_back(p),flag[p]=1;
    		    }for(int i=0;i<ans.size();i++)flag[ans[i]]=0;
            for(int i=0;i<ans.size();i++)tot+=r[ans[i]];
            ans.clear(); printf("%I64d
    ",tot);
    	  }
    }sam;
    int n;
    int main(){
        sam.build();
        scanf("%d",&n);
        for(int i=1;i<=n;i++)sam.solve();
        return 0;
    }
    

      

  • 相关阅读:
    redis skiplist性能实验
    python批量插mysql 2种方法 对比 装饰器timer
    数仓 & 数据湖小结
    mongo 增量同步之 MongoShake(3) kafka python处理kafka oplog mongoUtils
    mongo 增量同步之 MongoShake(2) kafka json to python json
    python swich case
    mongodb 增量同步之 MongoShake(1)
    redis scan & kyes p*
    SpringContextUtils Spring 工具类
    Google EventBus使用详解
  • 原文地址:https://www.cnblogs.com/forever97/p/codeforces235c.html
Copyright © 2011-2022 走看看