程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> hdu 2896 病毒侵襲 -- AC自動機

hdu 2896 病毒侵襲 -- AC自動機

編輯:C++入門知識

[cpp]
/*
尋找都有哪些子串
不能保證是字母或數字,所以子節點有差不多130個
*/ 
#include    
#include  
#include  
using namespace std;  
   
int biaoshi[510]; 
const int kind = 130;  
int dulist[10]; 
struct node{   
    node *fail;       //失敗指針  
    node *next[kind];  
    int count;        //是否為該單詞的最後一個節點  
    node(){           //構造函數初始化  
        fail=NULL;  
        count=0;  
        memset(next,NULL,sizeof(next));  
    }  
}*q[5000000];          //隊列,方便用於bfs構造失敗指針  
char keyword[510];     //輸入的單詞  
char str[1000010];    //模式串  
int head,tail;        //隊列的頭尾指針  
   
void insert(char *str,node *root,int no){  
    node *p=root;  
    int i=0,index;   
    while(str[i]){  
        index=str[i]-31;  
        if(p->next[index]==NULL) p->next[index]=new node();   
        p=p->next[index]; 
        i++; 
    }  
    p->count=no;//初始化為0,++後為1,表示是一個單詞的結尾  
}  
void build_ac_automation(node *root) 

    int i; 
    root->fail=NULL;  
    q[head++]=root;  
    while(head!=tail) 
    {  
        node *temp=q[tail++];//拿到一個節點  
        node *p=NULL;  
        for(i=0;i<130;i++) 
        {  
            if(temp->next[i]!=NULL)//若其i孩子非空  
            {  
                if(temp==root) //他自己是頭,其孩子的失敗指針指向頭  
                    temp->next[i]->fail=root;                  
                else{ //普通節點  
                    p=temp->fail; //指向自己的失敗指針  
                    while(p!=NULL) 
                    {   
                        if(p->next[i]!=NULL)//失敗指針有i孩子  
                        {  
                            temp->next[i]->fail=p->next[i]; //當前節點的i孩子的失敗指針指向失敗指針的i孩子,然後跳出  
                            break;  
                        }  
                        p=p->fail; //繼續找失敗指針  
                    }  
                    if(p==NULL) //若失敗指針為空  
                        temp->next[i]->fail=root; //當前節點的i孩子的失敗指針指向頭  
                }  
                q[head++]=temp->next[i];  //進去的都是定義過失敗指針的,故此過程是給其孩子定義失敗指針  
            }  
        }    
    }  
}  
int query(node *root) 
{  
    int i=0,cnt=0,index,len=strlen(str);  
    node *p=root;   
    while(str[i]) 
    {   
        index=str[i]-31;  //計算孩子的位置  
        while(p->next[index]==NULL && p!=root)  
            p=p->fail; //若沒有i孩子節點,通過失敗指針找與這之前相同的有i孩子的節點  
        p=p->next[index]; //指向其i孩子  
        p=(p==NULL)?root:p;  
        node *temp=p;  
        while(temp!=root && temp->count) 
        {  
            if(temp->count&&!biaoshi[temp->count])//主要是改這裡  
            { 
                cnt++; 
                biaoshi[temp->count]=1; 
            } 
            temp=temp->fail;  
        }  
        i++;                  
    }     
    return cnt;  
}  
int cmp(const void *a,const void *b) 

    int *c=(int*)a,*d=(int*)b; 
    return *c-*d; 

void print(int ji,int na,int n) 

 
    printf("web %d:",na); 
    for(int i=1;i<=n;++i) 
    { 
        if(biaoshi[i]) 
        { 
        printf(" %d",i); 
        } 
    } 
    printf("\n"); 

int main(){  
    int n,t,i,j=0;  
    while(scanf("%d",&n)!=EOF) 
    {   
        head=tail=0;  
        node *root=new node();  
       
        getchar();  
        for(i=1;i<=n;i++) 
        { 
            gets(keyword);  
            insert(keyword,root,i);  
        }  
        build_ac_automation(root);  
        scanf("%d",&t); 
        for(i=1;i<=t;++i) 
        { 
            memset(biaoshi,0,sizeof(biaoshi)); 
            scanf("%s",str);  
            int ge=query(root); 
            if(ge) 
            { 
                print(ge,i,n); 
                j++; 
            } 
        } 
        printf("total: %d\n",j); 
    }  
    return 0;  

/*
尋找都有哪些子串
不能保證是字母或數字,所以子節點有差不多130個
*/
#include
#include
#include
using namespace std;
 
int biaoshi[510];
const int kind = 130;
int dulist[10];
struct node{ 
    node *fail;       //失敗指針
    node *next[kind];
    int count;        //是否為該單詞的最後一個節點
    node(){           //構造函數初始化
        fail=NULL;
        count=0;
        memset(next,NULL,sizeof(next));
    }
}*q[5000000];          //隊列,方便用於bfs構造失敗指針
char keyword[510];     //輸入的單詞
char str[1000010];    //模式串
int head,tail;        //隊列的頭尾指針
 
void insert(char *str,node *root,int no){
    node *p=root;
    int i=0,index; 
    while(str[i]){
        index=str[i]-31;
        if(p->next[index]==NULL) p->next[index]=new node(); 
        p=p->next[index];
        i++;
    }
    p->count=no;//初始化為0,++後為1,表示是一個單詞的結尾
}
void build_ac_automation(node *root)
{
    int i;
    root->fail=NULL;
    q[head++]=root;
    while(head!=tail)
 {
        node *temp=q[tail++];//拿到一個節點
        node *p=NULL;
        for(i=0;i<130;i++)
  {
            if(temp->next[i]!=NULL)//若其i孩子非空
   {
                if(temp==root) //他自己是頭,其孩子的失敗指針指向頭
     temp->next[i]->fail=root;                
                else{ //普通節點
                    p=temp->fail; //指向自己的失敗指針
                    while(p!=NULL)
     { 
                        if(p->next[i]!=NULL)//失敗指針有i孩子
      {
                            temp->next[i]->fail=p->next[i]; //當前節點的i孩子的失敗指針指向失敗指針的i孩子,然後跳出
                            break;
                        }
                        p=p->fail; //繼續找失敗指針
                    }
                    if(p==NULL) //若失敗指針為空
      temp->next[i]->fail=root; //當前節點的i孩子的失敗指針指向頭
                }
                q[head++]=temp->next[i];  //進去的都是定義過失敗指針的,故此過程是給其孩子定義失敗指針
            }
        }  
    }
}
int query(node *root)
{
    int i=0,cnt=0,index,len=strlen(str);
    node *p=root; 
    while(str[i])
 { 
        index=str[i]-31;  //計算孩子的位置
        while(p->next[index]==NULL && p!=root)
   p=p->fail; //若沒有i孩子節點,通過失敗指針找與這之前相同的有i孩子的節點
        p=p->next[index]; //指向其i孩子
        p=(p==NULL)?root:p;
        node *temp=p;
        while(temp!=root && temp->count)
  {
   if(temp->count&&!biaoshi[temp->count])//主要是改這裡
   {
    cnt++;
    biaoshi[temp->count]=1;
   }
            temp=temp->fail;
        }
        i++;                
    }   
    return cnt;
}
int cmp(const void *a,const void *b)
{
 int *c=(int*)a,*d=(int*)b;
 return *c-*d;
}
void print(int ji,int na,int n)
{

 printf("web %d:",na);
 for(int i=1;i<=n;++i)
 {
  if(biaoshi[i])
  {
  printf(" %d",i);
  }
 }
 printf("\n");
}
int main(){
    int n,t,i,j=0;
    while(scanf("%d",&n)!=EOF)
 { 
        head=tail=0;
        node *root=new node();
     
        getchar();
        for(i=1;i<=n;i++)
  {
            gets(keyword);
            insert(keyword,root,i);
        }
        build_ac_automation(root);
  scanf("%d",&t);
  for(i=1;i<=t;++i)
  {
   memset(biaoshi,0,sizeof(biaoshi));
   scanf("%s",str);
   int ge=query(root);
   if(ge)
   {
    print(ge,i,n);
    j++;
   }
  }
  printf("total: %d\n",j);
    }
    return 0;
}


 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved