Computer Virus on Planet Pandora HDOJ3695

来源:互联网 发布:sar成像rd算法 编辑:程序博客网 时间:2024/05/22 02:15

AC自动机,要求模板串和其翻转串都是合法匹配,不用将模板串和其翻转串都加入到trie中,只要在匹配时把匹配串从正反俩个方向匹配一下就可以了,通过此题发现了以前AC自动机模板的一个错误(TLE到死),见代码吧


#include <iostream>#include <cstdio>#include <cstdlib>#include <cmath>#include <queue>#include <algorithm>#include <vector>#include <cstring>#include <stack>#include <cctype>#include <utility>   #include <map>#include <string>  #include <climits> #include <set>#include <string>    #include <sstream>#include <utility>   #include <ctime>using std::priority_queue;using std::vector;using std::swap;using std::stack;using std::sort;using std::max;using std::min;using std::pair;using std::map;using std::string;using std::cin;using std::cout;using std::set;using std::queue;using std::string;using std::istringstream;using std::make_pair;using std::getline;using std::greater;using std::endl;using std::multimap;using std::deque;typedef long long LL;typedef unsigned long long ULL;typedef pair<int, int> PAIR;typedef multimap<int, int> MMAP;const int MAXN(250010);const int SIGMA_SIZE(26);const int MAXM(110);const int MAXE(300010);const int MAXH(18);const int INFI((INT_MAX-1) >> 1);const int MOD(2520);const ULL BASE(31);const ULL LIM(1000000000000000ull);bool vis[260];struct AC{    int ch[MAXN][SIGMA_SIZE], f[MAXN];    int val[MAXN], last[MAXN];    int size;    inline int idx(char temp)    {        return temp-'A';    }    void init()    {        memset(ch[0], 0, sizeof(ch[0]));        val[0] = last[0] = 0;        size = 1;    }    void insert(char *S, int tv)    {        int u = 0, id;        for(; *S; ++S)        {            id = idx(*S);            if(!ch[u][id])            {                memset(ch[size], 0, sizeof(ch[size]));                val[size] = last[size] = 0;                ch[u][id] = size++;            }            u = ch[u][id];        }        val[u] = tv;    }    int que[MAXN];    int front, back;    void construct()    {        int cur, u;        front = back = 0;        for(int i = 0; i < SIGMA_SIZE; ++i)            if(ch[0][i])            {                u = ch[0][i];                f[u] = last[u] = 0;                que[back++] = u;            }        while(front < back)        {            cur = que[front++];            for(int i = 0; i < SIGMA_SIZE; ++i)            {                u = ch[cur][i];                if(u)                {                    f[u] = ch[f[cur]][i];                    last[u] = val[f[u]]? f[u]: last[f[u]];                    que[back++] = u;                }                else                    ch[cur][i] = ch[f[cur]][i];            }        }    }        void find(char *T)    {        int u = 0, id;        for(; *T; ++T)        {            id = idx(*T);            u = ch[u][id];            for(int pi = u; pi; )   //这里由于要求每个模板串只能加一次,所以可以把已经匹配过的模板忽略掉,否则每次都用last指针转移,TLE到死            {//类似如果每个节点的信息合并很好维护,就把这些具有相同后缀的节点信息合并起来,这样就不用使用last指针转移了,效率剧增                vis[val[pi]] = true;                int temp = last[pi];                last[pi] = 0;                pi = temp;            }        }    }};AC ac;char str[5100010];int main(){    int TC;    scanf("%d", &TC);    while(TC--)    {        int n;        scanf("%d", &n);        ac.init();        for(int i = 1; i <= n; ++i)        {            scanf("%s", str);            ac.insert(str, i);        }        ac.construct();        while(getchar() != '\n');        char temp;        int qua;        int len = 0;        while((temp = getchar()) != '\n')        {            if(temp >= 'A' && temp <= 'Z')                str[len++] = temp;            else            {                scanf("%d%c", &qua, &temp);                getchar();                for(int i = 0; i < qua; ++i)                    str[len++] = temp;            }        }        str[len] = '\0';        memset(vis, 0, sizeof(vis));        ac.find(str);        int s = 0, e = len-1;        while(s < e)            swap(str[s++], str[e--]);        ac.find(str);        int ans = 0;        for(int i = 1; i <= n; ++i)            if(vis[i])                ++ans;        printf("%d\n", ans);    }    return 0;}