poj 4042

题目意思是用主串去匹配模式串,如果a和b都在主串中出现了且a是b的子串,这只算b,求出能够匹配的模式串。

我的超时代码,不知道为什么就能超时。。。

#include <cstdlib>
#include <iostream>
#include <cstring>
#include <cstdio>

using namespace std;

const int CH=26;
const int NODE=6100000;
int chd[NODE][CH],fail[NODE],word[NODE],sz;
char s1[6100010],s2[6100010];
bool vis[3100];

void Ins(char *s,int val)
{
     int p=0;
     for(;*s;s++)
     {
          int id=(*s)-'A';         
          if(!chd[p][id])              
          {
                memset(chd[sz],0,sizeof(chd[sz]));                             
                word[sz]=0;
                chd[p][id]=sz++;
          }
          p=chd[p][id];
     }
     word[p]=val;
}
int Que[NODE];
void AC()
{
     int *s=Que,*e=Que;
     for(int i=0;i<CH;i++)
       if(chd[0][i]){
           *e++=chd[0][i];              
           fail[chd[0][i]]=0;
       }
     while(s!=e)
     {
         int p=*s++;           
         for(int i=0;i<CH;i++)
           if(chd[p][i])
           {
               int k=chd[p][i];          
               fail[k]=chd[fail[p]][i];
               *e++=chd[p][i];
           }
           else
             chd[p][i]=chd[fail[p]][i];
     }  
}
void change(char *s)
{
     int num=0;
     for(;*s;s++)     
       if((*s)=='[')
       {
             s++;        
             int cnt=(*s++)-'0';
             while((*s)>='0'&&(*s)<='9') cnt=cnt*10+(*s)-'0',s++;                          
             for(int i=0;i<cnt;i++) s2[num++]=(*s);
             s++;
       }
       else  s2[num++]=(*s);
       s2[num]='\0';
}
void solve()
{
     int p=0;
     for(int i=0;s2[i];i++)    
     {
             p=chd[p][s2[i]-'A'];     
             for(int tmp=fail[p];tmp>0&&word[tmp]>=0;tmp=fail[tmp])
              if(word[tmp]>0) 
              {
                 vis[word[tmp]]=1,word[tmp]=-1;  
                 break;
              }
     }
}
char ss[2510][1200];
void Ins1(char *s,int val)
{
     int p=0;
     for(;*s;s++)
     {
          int id=(*s)-'A';         
          if(!chd[p][id])              
          {
                memset(chd[sz],0,sizeof(chd[sz]));                             
                word[sz]=0;
                chd[p][id]=sz++;
          }
          p=chd[p][id];
          if(word[p]>0) vis[word[p]]=0;
     }
     word[p]=val;
}
void AC1()
{
     int *s=Que,*e=Que;
     for(int i=0;i<CH;i++)
       if(chd[0][i])
       {
           *e++=chd[0][i];              
           fail[chd[0][i]]=0;
       }
     while(s!=e)
     {
         int p=*s++;           
         for(int i=0;i<CH;i++)
           if(chd[p][i])
           {
               int k=chd[p][i];          
               fail[k]=chd[fail[p]][i];
               for(int tmp=fail[k];tmp>0;tmp=fail[tmp])
                 if(word[tmp]>=0) vis[word[tmp]]=0,word[tmp]=-1;
                 else break;
               *e++=chd[p][i];
           }
           else
             chd[p][i]=chd[fail[p]][i];
     }  
}
int main()
{
      int ca,n;
      scanf("%d",&ca);
      while(ca--)
      {
           scanf("%d",&n);
           getchar();
           sz=1;
           memset(chd[0],0,sizeof(chd[0]));   
           for(int i=0;i<n;i++)
           {
               scanf("%s",ss[i]);        
               change(ss[i]);
               Ins(s2,i+1);
           }
           AC();
           memset(vis,0,sizeof(vis));
           scanf("%s",s1); 
           change(s1);
           solve();
           sz=1;
           memset(chd[0],0,sizeof(chd[0]));
           for(int i=0;i<n;i++)
               if(vis[i+1]) Ins1(ss[i],i+1);        
           AC1();
           int ans=0;
           for(int i=1;i<=n;i++) if(vis[i]) ans++;
           printf("%d\n",ans);
      }
      return 0;    
}
/*
4
3
[2F]RR
RR
R
[4F]RRE
*/


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值