hdu 5164 Matching on Array (用map实现的ac自动机)

hdu 5164 Matching on Array (用map实现的ac自动机)

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=5164

题意:

给出长度为n一个母串,给出m个长度为ki子串,匹配的条件是比率相同,如子串4 8 能和 1 2 4匹配。问所有子串在母串中出现多少次。
限制:
1 <= n,m <= 1e5
1 <= ki <= 300000
思路:
赤裸裸的ac自动机啊,不过next数组用map来实现,出题人脑洞真大。

这里有一点还要注意,hdu的g++,结构体里面不能开太大的东西,要不然他ce了还不告诉你,所以把ac自动机结构体里面的东西全搬到外面就可以了。


/*hdu 5164 Matching on Array
  题意:
  给出长度为n一个母串,给出m个长度为ki子串,匹配的条件是比率相同,如子串4 8 能和 1 2 4匹配。问所有子串在母串中出现多少次。
  限制:
  1 <= n,m <= 1e5
  1 <= ki <= 300000
  思路:
  赤裸裸的ac自动机啊,不过next数组用map来实现,出题人脑洞真大。
  这里有一点还要注意,hdu的g++,结构体里面不能开太大的东西,要不然他ce了还不告诉你,所以把ac自动机结构体里面的东西全搬到外面就可以了。
 */
#include
   
   
    
    
#include
    
    
     
     
#include
     
     
#include
      
      
       
       
using namespace std;
#define LL __int64
const int N=1000005;
LL ans;
int s[N],p[3*N];
int n,m,q;

map
       
       
         next[N]; map 
        
          :: iterator it; int que[N],head,tail; int cnt,root,null; int fail[N],end[N]; struct acm{ int newNode(){ next[cnt].clear(); end[cnt]=0; return cnt++; } void init(){ cnt=0; null=cnt++; root=newNode(); } void insert(int n){ int now=root; for(int i=0;i 
         
           second]=root; que[tail++]=it->second; } while(head!=tail){ int now=que[head++]; end[now]+=end[fail[now]]; // for(it=next[now].begin();it!=next[now].end();++it){ int tmp=fail[now]; int nxt=next[tmp][it->first]; while(tmp!=null && !nxt){ tmp=fail[tmp]; nxt=next[tmp][it->first]; } if(tmp!=null) fail[it->second]=nxt; else fail[it->second]=root; que[tail++]=it->second; } } } void debug(){ for(int i=0;i<=cnt;i++){ printf("id=%3d,fail=%3d,sum=%3d\n",i,fail[i],end[i]); for(it=next[i].begin();it!=next[i].end();++it) printf("(%d,%d) ",it->first,it->second); puts(""); } } void query(int n){ int now=root; for(int i=0;i 
          
            1) acm.insert(m); else ans+=n; } acm.build(); //acm.debug(); acm.query(n); printf("%I64d\n",ans); } return 0; } 
           
          
         
       
      
      
    
    
   
   


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值