1. 程式人生 > >Keywords Search HDU

Keywords Search HDU

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

AC自動機模板題

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#include<queue>
using namespace std;
const int maxn=5e5+7;
struct AcTireNode
{
    int next[26];
    int fail,cnt;//要保證fail指標不能為自己
    AcTireNode()
    {
        memset(next,-1,sizeof(next));
        fail=cnt=0;//初始化
    }
    void clear()
    {
        memset(next,-1,sizeof(next));
        fail=cnt=0;//初始化
    }
};
class AcTire{
    /*
AC 自動機
1.輸入模式串 構建字典樹
2.構建fail指標
3.匹配文字串
4.初始化樹
*/
    public:
        AcTireNode *node;
        int top;//使用了多少個節點
    AcTire()
    {
        top=0;
        node=new AcTireNode[maxn];
    }
    inline int hash_letter(char c)
    {
        return c-'a';
    }
    void insert(char *p)
    {
        int now=0;
        while(*p)
        {
            if(node[now].next[hash_letter(*p)]==-1)
                node[now].next[hash_letter(*p)]=++top;
            now=node[now].next[hash_letter(*p)];
            ++p;
        }
        node[now].cnt++;
    }
    void bulid_fail()
    {
        int now=0;
        int to;
        /*
        保證佇列裡的fail指標全部OK
        從佇列中取一個 把其下面的fail指標OK 並且加入佇列
        */
        queue<int> mmp;
        for(int i=0;i<26;++i)//將根節點的所有兒子加入佇列
        {
            if(node[0].next[i]!=-1)
                mmp.push(node[0].next[i]);
        }
        while(!mmp.empty())//
        {
            now=mmp.front();
            mmp.pop();
            for(int i=0;i<26;++i)//將此節點的兒子的 fail指標計算出來並加入佇列
            {
                if(node[now].next[i]!=-1)
                {
                    mmp.push(node[now].next[i]);
                    /*   計算now的 第i個兒子的fail指標   */
                    to=node[now].fail;
                    while(to>0&&node[to].next[i]==-1)
                        to=node[to].fail;
                    /* 直至根節點 或者fail的父節點*/
                    if(node[to].next[i]!=-1)//否則沒有最大匹配  即為空
                        node[node[now].next[i]].fail=node[to].next[i];
                }
            }
        }

    }
    int Find_words(char *tx)
    {
        int ans=0;
        int now=0;//當前最大匹配下標
        int to,i;
        while(*tx)
        {
            i=hash_letter(*tx);
            //沒有下面的匹配,則找跟此字元的最大匹配
            while(now>0&&node[now].next[i]==-1)
                    now=node[now].fail;
            if(node[now].next[i]!=-1)
                now=node[now].next[i];
            /* 開始計算以now為字尾的單詞出現數*/
            to=now;
            while(to&&node[to].cnt!=-1)/*精髓之處,匹配過後設為-1代表該字尾對應所有的字串都匹配過了,避免後來重複匹配已經匹配過的單詞*/
            {
                ans+=node[to].cnt;
                node[to].cnt=-1;//標記該單詞已經加過了  就算這個單詞沒出現 標記為-1代表這個字串的字尾節點全掃描過了
                to=node[to].fail;
            }
            ++tx;
        }
        return ans;
    }
    void clear()
    {
        for(int i=0;i<=top;++i)
            node[i].clear();
        top=0;
    }
    ~AcTire()
    {
        delete []node;
    }

};
char tx[1000007],words[55];
int main()
{
    AcTire dch;
    int t;
    int n;

    scanf("%d",&t);
    while(t--)
    {
        dch.clear();
        scanf("%d",&n);
        for(int i=0;i<n;++i)
        {
            scanf("%s",words);
            dch.insert(words);
        }
        dch.bulid_fail();
        scanf("%s",tx);
        printf("%d\n",dch.Find_words(tx));
    }
}