HDU 2222 Kewords AC自动机

/*
TRIE结构,在使用前必须调用初始化init()!!!
主要调用Ins,ser,返回值都是TRIE中的下标;del,返回有无字符串(删除成功否)
*/
#include<stdio.h>
#include<iostream>
#include<memory.h>
#include<queue>
using namespace std;
const int CTNUM = 26;        //储存字母的数目
const int STRNUM = 510000;    //节点数目,绝对不能少于给定的字符串数目,一般给大点
const int MINCHAR='a';        //大小写分辨,如果混用或者不连续的话需要有对应的hash函数
struct TRIE
{
    int son[CTNUM];
    int count;
    int father;
}trie[STRNUM];
int fail[STRNUM];
int TNUM=1;
queue<int> q;
char s[12000][80],ss[1100000];
int dp[2000][2000],n;
char DNA[4]={'A','C','G','T'};
#define INT_MAX 10000000
void init()
{
    memset(&trie[0],0,sizeof(TRIE));
    memset(&trie[1],0,sizeof(TRIE));
    TNUM=2;
}
int Ins(char *str,int len)
{
    int i;
    int cur=1;
    for(i=0;i<len;i++)
    {
        if( !trie[cur].son[str[i]-MINCHAR] )
        {
            memset( &trie[TNUM],0,sizeof(TRIE) );
            trie[TNUM].father=cur;
            cur=trie[cur].son[str[i]-MINCHAR]=TNUM++;
        }
        else cur=trie[cur].son[str[i]-MINCHAR];
    }
    trie[cur].count++;
    return cur;
}
void calc_fail()
{
    int i,k,p;
    fail[0]=0;
    fail[1]=0;
    memset(fail,0,sizeof(fail));
    while(!q.empty()) q.pop();
    q.push(1);
    while(!q.empty())
    {
        i=q.front();
        q.pop();
    //    if (trie[fail[i]].count==1)
    //        trie[i].count=1;
     for(k='a'-MINCHAR;k<='z'-MINCHAR;k++)
        if (trie[i].son[k]!=0)
        {
            q.push(trie[i].son[k]);   
                  int p=fail[i];
                  while(p!=0&&trie[p].son[k]==0)
                      p=fail[p];
                  if (!p) fail[trie[i].son[k]]=1;
                  else
                        fail[trie[i].son[k]]=trie[p].son[k];
       
        }
    }
}

int min(int x,int y)
{
    if (x<y) return x;
    else return y;
}
int main()
{
   int i,j,t,ans,k,u,next,l,st,p;
   bool fl;
   u=0;
   scanf("%d",&n);
   while(scanf("%d",&n)!=EOF)
   {
       if (n==0) break;
     //  gets(ss);
       for(i=1;i<=n;i++)
          // gets(s[i]);
          scanf("%s",&s[i]);
//       gets(ss);
       scanf("%s",&ss);
       init();
               for(i=1;i<=n;i++)
           Ins(s[i],strlen(s[i]));
       calc_fail();
      // calc_tire();
       l=strlen(ss);
      ans=0;st=1;
      for(i=0;i<l;i++)
      {
          char ch=ss[i];
         while((st)&&(trie[st].son[ss[i]-MINCHAR]==0)) st=fail[st];
         if (!st) st=1;
          else st=trie[st].son[ss[i]-MINCHAR];
          p=st;
          while(p)
          {
           ans+=trie[p].count;
           trie[p].count=0;
           p=fail[p];
          }
      }
      cout<<ans<<endl;
   }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值