1. 程式人生 > >HDU--2222--Keywords Search--AC自己主動機

HDU--2222--Keywords Search--AC自己主動機

can ogl 設置斷點 cout engine imp cep bsp turn

Keywords Search

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 44594 Accepted Submission(s): 14056


Problem Description In the modern time, Search engine came into the life of everybody like Google, Baidu, etc.
Wiskey also wants to bring this feature to his image retrieval system.
Every image have a long description, when users type some keywords to find the image, the system will match the keywords with description of image and show the image which the most keywords be matched.
To simplify the problem, giving you a description of image, and some keywords, you should tell me how many keywords will be match.


Input First line will contain one integer means how many cases will follow by.
Each case will contain two integers N means the number of keywords and N keywords follow. (N <= 10000)
Each keyword will only contains characters ‘a‘-‘z‘, and the length will be not longer than 50.
The last line is the description, and the length will be not longer than 1000000.


Output Print how many keywords are contained in the description.


Sample Input
1
5
she
he
say
shr
her
yasherhs


Sample Output
3

題意:給定N個字符串,然後是一個文章。問你在文章中有多少個字符串是出現了的,不計算反復

ps:AC自己主動機,今天才學的。若有所感,非常easy,真的。在博客中發表了這個算法的學習。求共同進步。

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace

std;
struct
node
{

node *fail,*next[26];//fail:指向同級節點。當匹配失敗時跳轉。含義為x後綴包括的x同級節點整個串
int
x;
node
()//用來初始化
{

fail=NULL;
x=0;

for
(int i=0;i<26;i++)next[i]=NULL;
}
}*
root;
node *q[500010];

char
str[1000010];
void
setit(char *ss)//這是構建字典樹
{

int
i,j,k,l;
node *p=root;

for
(i=0;ss[i];i++)
{

k=ss[i]-‘a‘;

if
(p->next[k]==NULL)//假設下一個字符無節點
p->next[k]=new node();//創建並連接在p的後面
p=p->next[k
];
}

p->x
++;
}

void
ac()//AC自己主動機算法的構建,跟KMP的next
{

int
tail,head;
tail=head=0;
q[tail++]=root;//廣搜每一個節點。這樣是依照樹的深度一層一層來搜索,fail僅僅會僅僅想當前層以上的點,你懂的。


while
(head!=tail)
{

node *p=q[head++];//取出當前點

for
(int i=0;i<26;i++)//遍歷26個字符,這裏用ascll碼表示
if
(p->next[i]!=NULL)//假設存在
{

if
(p==root)//假設存在於根節點以下也就是第二層
{

p->next[i]->fail=root;//默認指向根節點,由於第一個字符都匹配錯誤,那可定從頭開始啊
q[tail++]=p->next[i];//入隊

continue
;
}

node *cur=p->fail;//取出查詢字符的上一層節點。用cur找它的同級節點

while
(cur!=NULL)//假設是空就結束,由於root的fail我初始化設定是NULL
{

if
(cur->next[i]!=NULL)//假設找到某個同級節點而且它後面有當前字符
{

p->next[i]->fail=cur->next[i];//把當前字符的fail指針指向同級節點後面的那個字符的位置

break
;
}

cur=cur->fail
;
}
//cout<<(p->next[i]==NULL?1:0)<<endl;
if(cur==NULL)//假設沒有找到合適的匹配
p->next[i]->fail=root;//那麽當前字符的fail就指向root根節點
q[tail++]=p->next[i
];//入隊
}
}
}

int
query()//在AC自己主動機算法處理後的字典樹中對字符串進行匹配
{

int
i,j,k,l,sum=0,cur;
node *p=root;

for
(i=0;str[i];i++)//遍歷每個字符
{

cur=str[i]-‘a‘;//取出字符

while
(p->next[cur]==NULL&&p!=root)//假設節點的後面沒有當前字符就繼續找同級。直到根節點
p=p->fail;

if
(p->next[cur]!=NULL)p=p->next[cur];//跳向當前字符所在節點。假設沒有找到合適,那麽p=root。所以推斷cur下一層是否有當前字符存在。不存在就繼續讓p指向root
node *q=p;//用q替代p來進行操作

while
(q!=root&&q->x!=-1)//查詢全部同級節點,直到root或者已經被查詢過
{

sum+=q->x;//把個數加起來
q->x=-1;//查詢過了就設置斷點
q=q->fail
;
}
}

return
sum;
}

int
main (void)
{

int
t,n,m,i,j,k,l;
scanf("%d",&t);

while
(t--&&scanf("%d",&n))
{

root=new node();

for
(i=0;i<n;i++)
{

char
ss[55];
scanf("%s",ss);
setit(ss
);
}

ac();
//cout<<"A"<<endl;
scanf("%s",str);
printf("%d\n",query
());
}

return
0;
}

HDU--2222--Keywords Search--AC自己主動機